summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.mailmap1
-rw-r--r--Documentation/ABI/testing/sysfs-bus-pci2
-rw-r--r--Documentation/DocBook/device-drivers.tmpl10
-rw-r--r--Documentation/DocBook/drm.tmpl17
-rw-r--r--Documentation/DocBook/media/Makefile2
-rw-r--r--Documentation/acpi/enumeration.txt2
-rw-r--r--Documentation/debugging-via-ohci1394.txt13
-rw-r--r--Documentation/device-mapper/thin-provisioning.txt5
-rw-r--r--Documentation/devicetree/bindings/arm/arch_timer.txt3
-rw-r--r--Documentation/devicetree/bindings/arm/marvell,kirkwood.txt97
-rw-r--r--Documentation/devicetree/bindings/ata/apm-xgene.txt3
-rw-r--r--Documentation/devicetree/bindings/clock/at91-clock.txt2
-rw-r--r--Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt2
-rw-r--r--Documentation/devicetree/bindings/dma/ti-edma.txt4
-rw-r--r--Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt6
-rw-r--r--Documentation/devicetree/bindings/hsi/client-devices.txt44
-rw-r--r--Documentation/devicetree/bindings/hsi/nokia-modem.txt57
-rw-r--r--Documentation/devicetree/bindings/hsi/omap-ssi.txt97
-rw-r--r--Documentation/devicetree/bindings/i2c/trivial-devices.txt16
-rw-r--r--Documentation/devicetree/bindings/mmc/mmci.txt54
-rw-r--r--Documentation/devicetree/bindings/net/arc_emac.txt12
-rw-r--r--Documentation/devicetree/bindings/net/ethernet.txt2
-rw-r--r--Documentation/devicetree/bindings/net/mdio-gpio.txt2
-rw-r--r--Documentation/devicetree/bindings/net/socfpga-dwmac.txt2
-rw-r--r--Documentation/devicetree/bindings/net/stmmac.txt2
-rw-r--r--Documentation/devicetree/bindings/pinctrl/brcm,bcm11351-pinctrl.txt2
-rw-r--r--Documentation/devicetree/bindings/pinctrl/pinctrl-st.txt4
-rw-r--r--Documentation/devicetree/bindings/serial/efm32-uart.txt4
-rw-r--r--Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt2
-rw-r--r--Documentation/devicetree/bindings/sound/tlv320aic31xx.txt6
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.txt18
-rw-r--r--Documentation/driver-model/devres.txt7
-rw-r--r--Documentation/email-clients.txt15
-rw-r--r--Documentation/filesystems/proc.txt5
-rw-r--r--Documentation/gpio/driver.txt59
-rw-r--r--Documentation/hsi.txt75
-rw-r--r--Documentation/hwmon/sysfs-interface14
-rw-r--r--Documentation/input/elantech.txt5
-rw-r--r--Documentation/ja_JP/HOWTO2
-rw-r--r--Documentation/ja_JP/stable_kernel_rules.txt6
-rw-r--r--Documentation/java.txt8
-rw-r--r--Documentation/kernel-parameters.txt23
-rw-r--r--Documentation/magic-number.txt12
-rw-r--r--Documentation/networking/filter.txt2
-rw-r--r--Documentation/networking/packet_mmap.txt2
-rw-r--r--Documentation/networking/scaling.txt2
-rw-r--r--Documentation/serial/00-INDEX8
-rw-r--r--Documentation/serial/digiepca.txt98
-rw-r--r--Documentation/serial/riscom8.txt36
-rw-r--r--Documentation/serial/specialix.txt383
-rw-r--r--Documentation/serial/sx.txt294
-rw-r--r--Documentation/stable_kernel_rules.txt2
-rw-r--r--Documentation/virtual/kvm/api.txt2
-rw-r--r--Documentation/vm/numa_memory_policy.txt5
-rw-r--r--Documentation/zh_CN/HOWTO2
-rw-r--r--Documentation/zh_CN/io_ordering.txt67
-rw-r--r--Documentation/zh_CN/magic-number.txt12
-rw-r--r--Documentation/zh_CN/stable_kernel_rules.txt2
-rw-r--r--MAINTAINERS74
-rw-r--r--Makefile2
-rw-r--r--arch/arc/include/asm/barrier.h37
-rw-r--r--arch/arc/kernel/entry.S8
-rw-r--r--arch/arm/Kconfig17
-rw-r--r--arch/arm/Kconfig.debug12
-rw-r--r--arch/arm/boot/dts/Makefile20
-rw-r--r--arch/arm/boot/dts/am335x-bone-common.dtsi4
-rw-r--r--arch/arm/boot/dts/am335x-evm.dts8
-rw-r--r--arch/arm/boot/dts/am335x-evmsk.dts4
-rw-r--r--arch/arm/boot/dts/am335x-igep0033.dtsi5
-rw-r--r--arch/arm/boot/dts/am33xx.dtsi12
-rw-r--r--arch/arm/boot/dts/am3517.dtsi16
-rw-r--r--arch/arm/boot/dts/am4372.dtsi4
-rw-r--r--arch/arm/boot/dts/am437x-gp-evm.dts5
-rw-r--r--arch/arm/boot/dts/armada-370-db.dts1
-rw-r--r--arch/arm/boot/dts/armada-370-xp.dtsi1
-rw-r--r--arch/arm/boot/dts/armada-375-db.dts5
-rw-r--r--arch/arm/boot/dts/armada-380.dtsi2
-rw-r--r--arch/arm/boot/dts/armada-385.dtsi4
-rw-r--r--arch/arm/boot/dts/armada-38x.dtsi1
-rw-r--r--arch/arm/boot/dts/armada-xp-db.dts2
-rw-r--r--arch/arm/boot/dts/armada-xp-gp.dts10
-rw-r--r--arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts2
-rw-r--r--arch/arm/boot/dts/at91-sama5d3_xplained.dts4
-rw-r--r--arch/arm/boot/dts/at91sam9260.dtsi2
-rw-r--r--arch/arm/boot/dts/at91sam9261.dtsi2
-rw-r--r--arch/arm/boot/dts/at91sam9rl.dtsi2
-rw-r--r--arch/arm/boot/dts/dra7.dtsi4
-rw-r--r--arch/arm/boot/dts/dra7xx-clocks.dtsi2
-rw-r--r--arch/arm/boot/dts/exynos4412-trats2.dts2
-rw-r--r--arch/arm/boot/dts/exynos5250-arndale.dts1
-rw-r--r--arch/arm/boot/dts/exynos5420-arndale-octa.dts12
-rw-r--r--arch/arm/boot/dts/exynos5420.dtsi24
-rw-r--r--arch/arm/boot/dts/imx25.dtsi1
-rw-r--r--arch/arm/boot/dts/imx27-apf27.dts1
-rw-r--r--arch/arm/boot/dts/imx27.dtsi1
-rw-r--r--arch/arm/boot/dts/imx50.dtsi4
-rw-r--r--arch/arm/boot/dts/imx51.dtsi4
-rw-r--r--arch/arm/boot/dts/imx53-m53evk.dts23
-rw-r--r--arch/arm/boot/dts/imx53-mba53.dts2
-rw-r--r--arch/arm/boot/dts/imx53-qsb-common.dtsi3
-rw-r--r--arch/arm/boot/dts/imx53-tx53-x03x.dts11
-rw-r--r--arch/arm/boot/dts/imx53.dtsi8
-rw-r--r--arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts48
-rw-r--r--arch/arm/boot/dts/imx6q-gw5400-a.dts3
-rw-r--r--arch/arm/boot/dts/imx6qdl-gw52xx.dtsi3
-rw-r--r--arch/arm/boot/dts/imx6qdl-microsom-ar8035.dtsi22
-rw-r--r--arch/arm/boot/dts/imx6qdl.dtsi13
-rw-r--r--arch/arm/boot/dts/imx6sl-evk.dts1
-rw-r--r--arch/arm/boot/dts/imx6sl.dtsi4
-rw-r--r--arch/arm/boot/dts/kirkwood-b3.dts2
-rw-r--r--arch/arm/boot/dts/kirkwood-cloudbox.dts2
-rw-r--r--arch/arm/boot/dts/kirkwood-dreamplug.dts2
-rw-r--r--arch/arm/boot/dts/kirkwood-laplug.dts2
-rw-r--r--arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts20
-rw-r--r--arch/arm/boot/dts/kirkwood-ns2-common.dtsi4
-rw-r--r--arch/arm/boot/dts/kirkwood-nsa310-common.dtsi18
-rw-r--r--arch/arm/boot/dts/kirkwood-nsa310.dts2
-rw-r--r--arch/arm/boot/dts/kirkwood-nsa310a.dts2
-rw-r--r--arch/arm/boot/dts/kirkwood-openblocks_a6.dts2
-rw-r--r--arch/arm/boot/dts/kirkwood-openblocks_a7.dts2
-rw-r--r--arch/arm/boot/dts/kirkwood-t5325.dts5
-rw-r--r--arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi19
-rw-r--r--arch/arm/boot/dts/omap2.dtsi7
-rw-r--r--arch/arm/boot/dts/omap2420.dtsi8
-rw-r--r--arch/arm/boot/dts/omap2430.dtsi7
-rw-r--r--arch/arm/boot/dts/omap3-beagle-xm-ab.dts16
-rw-r--r--arch/arm/boot/dts/omap3-cm-t3x30.dtsi66
-rw-r--r--arch/arm/boot/dts/omap3-devkit8000.dts1
-rw-r--r--arch/arm/boot/dts/omap3-igep.dtsi2
-rw-r--r--arch/arm/boot/dts/omap3-igep0020.dts4
-rw-r--r--arch/arm/boot/dts/omap3-lilly-a83x.dtsi1
-rw-r--r--arch/arm/boot/dts/omap3-sb-t35.dtsi37
-rw-r--r--arch/arm/boot/dts/omap3-sbc-t3517.dts13
-rw-r--r--arch/arm/boot/dts/omap3.dtsi4
-rw-r--r--arch/arm/boot/dts/omap4.dtsi4
-rw-r--r--arch/arm/boot/dts/omap5.dtsi17
-rw-r--r--arch/arm/boot/dts/r8a7740.dtsi1
-rw-r--r--arch/arm/boot/dts/r8a7790-lager.dts4
-rw-r--r--arch/arm/boot/dts/r8a7791-koelsch.dts6
-rw-r--r--arch/arm/boot/dts/rk3188.dtsi8
-rw-r--r--arch/arm/boot/dts/sama5d3.dtsi2
-rw-r--r--arch/arm/boot/dts/sama5d3_mci2.dtsi2
-rw-r--r--arch/arm/boot/dts/sama5d3_tcb1.dtsi2
-rw-r--r--arch/arm/boot/dts/sama5d3_uart.dtsi2
-rw-r--r--arch/arm/boot/dts/sh73a0.dtsi1
-rw-r--r--arch/arm/boot/dts/spear320-hmi.dts2
-rw-r--r--arch/arm/boot/dts/ste-ccu8540.dts1
-rw-r--r--arch/arm/boot/dts/ste-ccu9540.dts6
-rw-r--r--arch/arm/boot/dts/ste-href.dtsi19
-rw-r--r--arch/arm/boot/dts/ste-nomadik-stn8815.dtsi4
-rw-r--r--arch/arm/boot/dts/ste-snowball.dts4
-rw-r--r--arch/arm/boot/dts/ste-u300.dts4
-rw-r--r--arch/arm/boot/dts/stih415-pinctrl.dtsi10
-rw-r--r--arch/arm/boot/dts/stih416-pinctrl.dtsi10
-rw-r--r--arch/arm/boot/dts/sun7i-a20.dtsi14
-rw-r--r--arch/arm/boot/dts/tegra124.dtsi13
-rw-r--r--arch/arm/boot/dts/vf610-twr.dts2
-rw-r--r--arch/arm/boot/dts/vf610.dtsi4
-rw-r--r--arch/arm/boot/dts/zynq-7000.dtsi23
-rw-r--r--arch/arm/boot/dts/zynq-zc702.dts76
-rw-r--r--arch/arm/boot/dts/zynq-zc706.dts68
-rw-r--r--arch/arm/common/bL_switcher.c16
-rw-r--r--arch/arm/common/edma.c48
-rw-r--r--arch/arm/common/mcpm_entry.c5
-rw-r--r--arch/arm/configs/bcm_defconfig2
-rw-r--r--arch/arm/configs/exynos_defconfig1
-rw-r--r--arch/arm/configs/omap2plus_defconfig2
-rw-r--r--arch/arm/configs/sunxi_defconfig2
-rw-r--r--arch/arm/configs/u300_defconfig4
-rw-r--r--arch/arm/configs/u8500_defconfig24
-rw-r--r--arch/arm/include/asm/cputype.h14
-rw-r--r--arch/arm/include/asm/div64.h2
-rw-r--r--arch/arm/include/asm/mcpm.h7
-rw-r--r--arch/arm/include/asm/tlb.h12
-rw-r--r--arch/arm/include/asm/trusted_foundations.h2
-rw-r--r--arch/arm/include/asm/uaccess.h3
-rw-r--r--arch/arm/include/asm/xen/hypercall.h16
-rw-r--r--arch/arm/include/asm/xen/interface.h2
-rw-r--r--arch/arm/include/asm/xen/page.h1
-rw-r--r--arch/arm/include/uapi/asm/unistd.h1
-rw-r--r--arch/arm/kernel/Makefile1
-rw-r--r--arch/arm/kernel/calls.S1
-rw-r--r--arch/arm/kernel/entry-header.S4
-rw-r--r--arch/arm/kernel/head.S2
-rw-r--r--arch/arm/kernel/iwmmxt.S8
-rw-r--r--arch/arm/kernel/machine_kexec.c7
-rw-r--r--arch/arm/kernel/pj4-cp0.c42
-rw-r--r--arch/arm/kernel/sys_oabi-compat.c6
-rw-r--r--arch/arm/kernel/unwind.c2
-rw-r--r--arch/arm/kvm/Kconfig2
-rw-r--r--arch/arm/kvm/mmu.c15
-rw-r--r--arch/arm/mach-at91/at91sam9260_devices.c10
-rw-r--r--arch/arm/mach-at91/at91sam9g45_devices.c2
-rw-r--r--arch/arm/mach-exynos/firmware.c15
-rw-r--r--arch/arm/mach-imx/clk-imx6q.c29
-rw-r--r--arch/arm/mach-imx/devices/platform-ipu-core.c2
-rw-r--r--arch/arm/mach-lpc32xx/phy3250.c3
-rw-r--r--arch/arm/mach-mvebu/mvebu-soc-id.c13
-rw-r--r--arch/arm/mach-omap2/board-flash.c2
-rw-r--r--arch/arm/mach-omap2/board-rx51-video.c2
-rw-r--r--arch/arm/mach-omap2/cclock3xxx_data.c3
-rw-r--r--arch/arm/mach-omap2/clkt_dpll.c4
-rw-r--r--arch/arm/mach-omap2/cpuidle44xx.c25
-rw-r--r--arch/arm/mach-omap2/gpmc.c15
-rw-r--r--arch/arm/mach-omap2/omap-headsmp.S8
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c3
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_3xxx_data.c4
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_54xx_data.c2
-rw-r--r--arch/arm/mach-omap2/pm34xx.c4
-rw-r--r--arch/arm/mach-orion5x/common.h2
-rw-r--r--arch/arm/mach-pxa/include/mach/hx4700.h1
-rw-r--r--arch/arm/mach-rockchip/platsmp.c2
-rw-r--r--arch/arm/mach-shmobile/board-armadillo800eva.c1
-rw-r--r--arch/arm/mach-shmobile/board-lager.c4
-rw-r--r--arch/arm/mach-shmobile/clock-r8a7778.c2
-rw-r--r--arch/arm/mach-spear/headsmp.S2
-rw-r--r--arch/arm/mach-spear/platsmp.c2
-rw-r--r--arch/arm/mach-spear/time.c4
-rw-r--r--arch/arm/mach-tegra/Kconfig3
-rw-r--r--arch/arm/mach-ux500/Makefile3
-rw-r--r--arch/arm/mach-ux500/board-mop500-sdi.c166
-rw-r--r--arch/arm/mach-ux500/board-mop500.h5
-rw-r--r--arch/arm/mach-ux500/cpu-db8500.c4
-rw-r--r--arch/arm/mach-vexpress/dcscb.c7
-rw-r--r--arch/arm/mach-vexpress/spc.c4
-rw-r--r--arch/arm/mm/Kconfig8
-rw-r--r--arch/arm/mm/dma-mapping.c2
-rw-r--r--arch/arm/mm/proc-v7m.S8
-rw-r--r--arch/arm/plat-omap/dma.c10
-rw-r--r--arch/arm/vfp/vfpdouble.c2
-rw-r--r--arch/arm/vfp/vfpsingle.c2
-rw-r--r--arch/arm/xen/enlighten.c9
-rw-r--r--arch/arm/xen/hypercall.S1
-rw-r--r--arch/arm64/Kconfig2
-rw-r--r--arch/arm64/boot/dts/apm-storm.dtsi3
-rw-r--r--arch/arm64/include/asm/memory.h1
-rw-r--r--arch/arm64/include/asm/mmu.h3
-rw-r--r--arch/arm64/include/asm/pgtable.h2
-rw-r--r--arch/arm64/include/asm/tlb.h6
-rw-r--r--arch/arm64/include/asm/unistd32.h3
-rw-r--r--arch/arm64/kernel/debug-monitors.c3
-rw-r--r--arch/arm64/kernel/early_printk.c6
-rw-r--r--arch/arm64/kernel/irq.c10
-rw-r--r--arch/arm64/kernel/setup.c3
-rw-r--r--arch/arm64/kernel/time.c2
-rw-r--r--arch/arm64/mm/dma-mapping.c35
-rw-r--r--arch/arm64/mm/hugetlbpage.c4
-rw-r--r--arch/arm64/mm/mmu.c3
-rw-r--r--arch/arm64/xen/hypercall.S1
-rw-r--r--arch/hexagon/include/asm/barrier.h37
-rw-r--r--arch/ia64/include/asm/tlb.h42
-rw-r--r--arch/ia64/include/asm/unistd.h2
-rw-r--r--arch/ia64/include/uapi/asm/unistd.h1
-rw-r--r--arch/ia64/kernel/entry.S1
-rw-r--r--arch/ia64/kernel/head.S2
-rw-r--r--arch/ia64/kernel/ivt.S2
-rw-r--r--arch/ia64/kvm/vmm_ivt.S2
-rw-r--r--arch/m68k/Kconfig.debug9
-rw-r--r--arch/m68k/amiga/amisound.c2
-rw-r--r--arch/m68k/amiga/config.c20
-rw-r--r--arch/m68k/apollo/config.c20
-rw-r--r--arch/m68k/atari/stram.c71
-rw-r--r--arch/m68k/configs/amiga_defconfig5
-rw-r--r--arch/m68k/configs/apollo_defconfig5
-rw-r--r--arch/m68k/configs/atari_defconfig5
-rw-r--r--arch/m68k/configs/bvme6000_defconfig5
-rw-r--r--arch/m68k/configs/hp300_defconfig5
-rw-r--r--arch/m68k/configs/mac_defconfig5
-rw-r--r--arch/m68k/configs/multi_defconfig5
-rw-r--r--arch/m68k/configs/mvme147_defconfig5
-rw-r--r--arch/m68k/configs/mvme16x_defconfig5
-rw-r--r--arch/m68k/configs/q40_defconfig5
-rw-r--r--arch/m68k/configs/sun3_defconfig5
-rw-r--r--arch/m68k/configs/sun3x_defconfig5
-rw-r--r--arch/m68k/hp300/config.c11
-rw-r--r--arch/m68k/include/asm/atari_stram.h2
-rw-r--r--arch/m68k/include/asm/unistd.h2
-rw-r--r--arch/m68k/include/uapi/asm/unistd.h1
-rw-r--r--arch/m68k/kernel/Makefile2
-rw-r--r--arch/m68k/kernel/early_printk.c67
-rw-r--r--arch/m68k/kernel/head.S207
-rw-r--r--arch/m68k/kernel/syscalltable.S1
-rw-r--r--arch/m68k/mac/config.c29
-rw-r--r--arch/m68k/mm/motorola.c10
-rw-r--r--arch/m68k/mvme16x/config.c26
-rw-r--r--arch/metag/include/asm/barrier.h3
-rw-r--r--arch/metag/include/asm/processor.h2
-rw-r--r--arch/metag/include/uapi/asm/Kbuild2
-rw-r--r--arch/metag/include/uapi/asm/resource.h7
-rw-r--r--arch/mips/Makefile2
-rw-r--r--arch/mips/cavium-octeon/octeon-irq.c2
-rw-r--r--arch/mips/dec/ecc-berr.c1
-rw-r--r--arch/mips/dec/kn02xa-berr.c1
-rw-r--r--arch/mips/dec/prom/Makefile1
-rw-r--r--arch/mips/dec/prom/call_o32.S89
-rw-r--r--arch/mips/fw/lib/call_o32.S57
-rw-r--r--arch/mips/fw/sni/sniprom.c3
-rw-r--r--arch/mips/include/asm/cpu-info.h4
-rw-r--r--arch/mips/include/asm/dec/prom.h48
-rw-r--r--arch/mips/include/asm/rm9k-ocd.h56
-rw-r--r--arch/mips/include/asm/syscall.h2
-rw-r--r--arch/mips/include/uapi/asm/inst.h398
-rw-r--r--arch/mips/include/uapi/asm/unistd.h15
-rw-r--r--arch/mips/kernel/branch.c8
-rw-r--r--arch/mips/kernel/proc.c9
-rw-r--r--arch/mips/kernel/ptrace.c14
-rw-r--r--arch/mips/kernel/scall32-o32.S1
-rw-r--r--arch/mips/kernel/scall64-64.S1
-rw-r--r--arch/mips/kernel/scall64-n32.S1
-rw-r--r--arch/mips/kernel/scall64-o32.S1
-rw-r--r--arch/mips/kernel/traps.c4
-rw-r--r--arch/mips/lantiq/dts/easy50712.dts1
-rw-r--r--arch/mips/lib/csum_partial.S9
-rw-r--r--arch/mips/lib/delay.c14
-rw-r--r--arch/mips/lib/strncpy_user.S13
-rw-r--r--arch/mips/loongson/Kconfig1
-rw-r--r--arch/mips/loongson/common/cs5536/cs5536_mfgpt.c11
-rw-r--r--arch/mips/loongson/lemote-2f/clock.c5
-rw-r--r--arch/mips/mm/cache.c4
-rw-r--r--arch/mips/mm/page.c4
-rw-r--r--arch/mips/mm/tlb-funcs.S4
-rw-r--r--arch/mips/mm/tlbex.c7
-rw-r--r--arch/mips/mti-malta/malta-memory.c2
-rw-r--r--arch/mips/pci/pci-rc32434.c1
-rw-r--r--arch/mips/ralink/dts/mt7620a_eval.dts1
-rw-r--r--arch/mips/ralink/dts/rt2880_eval.dts1
-rw-r--r--arch/mips/ralink/dts/rt3052_eval.dts1
-rw-r--r--arch/mips/ralink/dts/rt3883_eval.dts1
-rw-r--r--arch/parisc/Kconfig1
-rw-r--r--arch/parisc/include/asm/processor.h5
-rw-r--r--arch/parisc/include/asm/shmparam.h5
-rw-r--r--arch/parisc/include/uapi/asm/Kbuild3
-rw-r--r--arch/parisc/include/uapi/asm/resource.h7
-rw-r--r--arch/parisc/include/uapi/asm/unistd.h3
-rw-r--r--arch/parisc/kernel/cache.c3
-rw-r--r--arch/parisc/kernel/sys_parisc.c20
-rw-r--r--arch/parisc/kernel/syscall.S12
-rw-r--r--arch/parisc/kernel/syscall_table.S3
-rw-r--r--arch/parisc/kernel/traps.c54
-rw-r--r--arch/parisc/lib/memcpy.c2
-rw-r--r--arch/parisc/mm/fault.c46
-rw-r--r--arch/powerpc/Makefile4
-rw-r--r--arch/powerpc/boot/main.c8
-rw-r--r--arch/powerpc/boot/ops.h2
-rw-r--r--arch/powerpc/boot/ps3.c4
-rw-r--r--arch/powerpc/include/asm/opal.h42
-rw-r--r--arch/powerpc/include/asm/ppc_asm.h7
-rw-r--r--arch/powerpc/include/asm/sections.h11
-rw-r--r--arch/powerpc/include/asm/systbl.h1
-rw-r--r--arch/powerpc/include/asm/unistd.h2
-rw-r--r--arch/powerpc/include/uapi/asm/setup.h7
-rw-r--r--arch/powerpc/include/uapi/asm/unistd.h1
-rw-r--r--arch/powerpc/kernel/kvm.c2
-rw-r--r--arch/powerpc/kernel/machine_kexec_64.c2
-rw-r--r--arch/powerpc/kernel/pci_64.c10
-rw-r--r--arch/powerpc/kernel/ppc_ksyms.c1
-rw-r--r--arch/powerpc/kernel/rtas_flash.c2
-rw-r--r--arch/powerpc/kernel/time.c3
-rw-r--r--arch/powerpc/kvm/book3s.c6
-rw-r--r--arch/powerpc/kvm/book3s_hv_rm_mmu.c2
-rw-r--r--arch/powerpc/kvm/book3s_hv_rmhandlers.S122
-rw-r--r--arch/powerpc/kvm/book3s_pr.c6
-rw-r--r--arch/powerpc/mm/hash_native_64.c38
-rw-r--r--arch/powerpc/mm/hash_utils_64.c4
-rw-r--r--arch/powerpc/mm/numa.c1
-rw-r--r--arch/powerpc/perf/hv-24x7.c35
-rw-r--r--arch/powerpc/perf/hv-gpci.c6
-rw-r--r--arch/powerpc/platforms/powernv/eeh-ioda.c3
-rw-r--r--arch/powerpc/platforms/powernv/opal-dump.c94
-rw-r--r--arch/powerpc/platforms/powernv/opal-elog.c11
-rw-r--r--arch/powerpc/platforms/powernv/opal-flash.c118
-rw-r--r--arch/powerpc/platforms/powernv/opal-sysparam.c32
-rw-r--r--arch/powerpc/platforms/powernv/opal.c69
-rw-r--r--arch/powerpc/platforms/powernv/pci-ioda.c3
-rw-r--r--arch/powerpc/platforms/powernv/setup.c48
-rw-r--r--arch/powerpc/platforms/powernv/smp.c3
-rw-r--r--arch/powerpc/platforms/pseries/hotplug-cpu.c5
-rw-r--r--arch/powerpc/platforms/pseries/hotplug-memory.c10
-rw-r--r--arch/powerpc/sysdev/ppc4xx_pci.c2
-rw-r--r--arch/s390/crypto/aes_s390.c3
-rw-r--r--arch/s390/crypto/des_s390.c3
-rw-r--r--arch/s390/include/asm/ccwgroup.h2
-rw-r--r--arch/s390/include/asm/sigp.h19
-rw-r--r--arch/s390/include/asm/smp.h13
-rw-r--r--arch/s390/include/asm/tlb.h13
-rw-r--r--arch/s390/include/uapi/asm/unistd.h3
-rw-r--r--arch/s390/kernel/compat_wrapper.c3
-rw-r--r--arch/s390/kernel/dumpstack.c8
-rw-r--r--arch/s390/kernel/ptrace.c2
-rw-r--r--arch/s390/kernel/setup.c32
-rw-r--r--arch/s390/kernel/smp.c15
-rw-r--r--arch/s390/kernel/syscalls.S1
-rw-r--r--arch/s390/kvm/kvm-s390.c1
-rw-r--r--arch/s390/lib/uaccess.c5
-rw-r--r--arch/s390/mm/fault.c140
-rw-r--r--arch/s390/net/bpf_jit_comp.c3
-rw-r--r--arch/sh/include/asm/tlb.h8
-rw-r--r--arch/sparc/include/asm/pgtable_64.h89
-rw-r--r--arch/sparc/include/asm/tsb.h3
-rw-r--r--arch/sparc/kernel/head_64.S4
-rw-r--r--arch/sparc/kernel/ktlb.S2
-rw-r--r--arch/sparc/kernel/nmi.c21
-rw-r--r--arch/sparc/kernel/smp_64.c6
-rw-r--r--arch/sparc/kernel/sys32.S2
-rw-r--r--arch/sparc/kernel/sysfs.c2
-rw-r--r--arch/sparc/kernel/unaligned_64.c12
-rw-r--r--arch/sparc/lib/NG2memcpy.S1
-rw-r--r--arch/sparc/mm/fault_64.c98
-rw-r--r--arch/sparc/mm/gup.c2
-rw-r--r--arch/sparc/mm/init_64.c12
-rw-r--r--arch/sparc/mm/tlb.c26
-rw-r--r--arch/sparc/mm/tsb.c14
-rw-r--r--arch/um/include/asm/tlb.h16
-rw-r--r--arch/um/include/shared/os.h1
-rw-r--r--arch/um/kernel/physmem.c1
-rw-r--r--arch/um/os-Linux/file.c6
-rw-r--r--arch/um/os-Linux/main.c1
-rw-r--r--arch/um/os-Linux/mem.c372
-rw-r--r--arch/x86/Makefile9
-rw-r--r--arch/x86/boot/Makefile4
-rw-r--r--arch/x86/boot/compressed/misc.c2
-rw-r--r--arch/x86/include/asm/hpet.h1
-rw-r--r--arch/x86/include/asm/hugetlb.h1
-rw-r--r--arch/x86/include/asm/kvm_host.h2
-rw-r--r--arch/x86/include/asm/page_64_types.h2
-rw-r--r--arch/x86/include/asm/xen/hypercall.h2
-rw-r--r--arch/x86/include/asm/xen/interface.h3
-rw-r--r--arch/x86/include/uapi/asm/msr-index.h2
-rw-r--r--arch/x86/kernel/acpi/sleep.c2
-rw-r--r--arch/x86/kernel/apic/io_apic.c7
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce.c4
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_intel.c18
-rw-r--r--arch/x86/kernel/cpu/mcheck/therm_throt.c4
-rw-r--r--arch/x86/kernel/cpu/mcheck/threshold.c4
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel.c1
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_rapl.c46
-rw-r--r--arch/x86/kernel/cpu/rdrand.c1
-rw-r--r--arch/x86/kernel/early-quirks.c18
-rw-r--r--arch/x86/kernel/head32.c2
-rw-r--r--arch/x86/kernel/head64.c2
-rw-r--r--arch/x86/kernel/hpet.c2
-rw-r--r--arch/x86/kernel/kprobes/core.c16
-rw-r--r--arch/x86/kernel/ldt.c4
-rw-r--r--arch/x86/kernel/process_64.c2
-rw-r--r--arch/x86/kernel/reboot.c82
-rw-r--r--arch/x86/kernel/smp.c2
-rw-r--r--arch/x86/kernel/traps.c6
-rw-r--r--arch/x86/kernel/vsmp_64.c17
-rw-r--r--arch/x86/kernel/vsyscall_gtod.c2
-rw-r--r--arch/x86/kvm/cpuid.c2
-rw-r--r--arch/x86/kvm/cpuid.h8
-rw-r--r--arch/x86/kvm/mmu.c38
-rw-r--r--arch/x86/kvm/mmu.h44
-rw-r--r--arch/x86/kvm/paging_tmpl.h2
-rw-r--r--arch/x86/kvm/vmx.c71
-rw-r--r--arch/x86/kvm/x86.c18
-rw-r--r--arch/x86/lguest/boot.c4
-rw-r--r--arch/x86/lib/msr.c2
-rw-r--r--arch/x86/math-emu/errors.c16
-rw-r--r--arch/x86/net/bpf_jit_comp.c2
-rw-r--r--arch/x86/platform/efi/early_printk.c83
-rw-r--r--arch/x86/platform/olpc/olpc-xo1-pm.c2
-rw-r--r--arch/x86/power/hibernate_64.c2
-rw-r--r--arch/x86/syscalls/Makefile2
-rw-r--r--arch/x86/syscalls/syscall_32.tbl1
-rw-r--r--arch/x86/tools/Makefile2
-rw-r--r--arch/x86/vdso/vdso-layout.lds.S19
-rw-r--r--arch/x86/vdso/vdso32-setup.c8
-rw-r--r--arch/x86/xen/enlighten.c3
-rw-r--r--arch/x86/xen/irq.c6
-rw-r--r--arch/x86/xen/mmu.c125
-rw-r--r--arch/x86/xen/p2m.c174
-rw-r--r--arch/x86/xen/setup.c15
-rw-r--r--arch/x86/xen/smp.c3
-rw-r--r--arch/x86/xen/spinlock.c5
-rw-r--r--arch/x86/xen/suspend.c23
-rw-r--r--arch/x86/xen/xen-asm_32.S25
-rw-r--r--arch/x86/xen/xen-ops.h2
-rw-r--r--arch/xtensa/Kconfig20
-rw-r--r--arch/xtensa/boot/dts/kc705.dts11
-rw-r--r--arch/xtensa/boot/dts/xtfpga-flash-128m.dtsi28
-rw-r--r--arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi48
-rw-r--r--arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi32
-rw-r--r--arch/xtensa/boot/dts/xtfpga.dtsi37
-rw-r--r--arch/xtensa/include/asm/bootparam.h13
-rw-r--r--arch/xtensa/include/asm/fixmap.h58
-rw-r--r--arch/xtensa/include/asm/highmem.h45
-rw-r--r--arch/xtensa/include/asm/pgtable.h4
-rw-r--r--arch/xtensa/include/asm/sysmem.h38
-rw-r--r--arch/xtensa/include/asm/tlbflush.h11
-rw-r--r--arch/xtensa/kernel/setup.c46
-rw-r--r--arch/xtensa/kernel/smp.c15
-rw-r--r--arch/xtensa/kernel/xtensa_ksyms.c7
-rw-r--r--arch/xtensa/mm/Makefile1
-rw-r--r--arch/xtensa/mm/cache.c7
-rw-r--r--arch/xtensa/mm/highmem.c72
-rw-r--r--arch/xtensa/mm/init.c299
-rw-r--r--arch/xtensa/mm/mmu.c36
-rw-r--r--arch/xtensa/mm/tlb.c15
-rw-r--r--arch/xtensa/platforms/iss/Makefile3
-rw-r--r--arch/xtensa/platforms/xt2000/setup.c12
-rw-r--r--block/blk-cgroup.c15
-rw-r--r--crypto/crypto_user.c2
-rw-r--r--drivers/Makefile6
-rw-r--r--drivers/acpi/Kconfig17
-rw-r--r--drivers/acpi/Makefile1
-rw-r--r--drivers/acpi/ac.c117
-rw-r--r--drivers/acpi/acpi_platform.c1
-rw-r--r--drivers/acpi/acpi_processor.c8
-rw-r--r--drivers/acpi/acpica/acglobal.h4
-rw-r--r--drivers/acpi/acpica/exfield.c104
-rw-r--r--drivers/acpi/acpica/tbutils.c7
-rw-r--r--drivers/acpi/battery.c329
-rw-r--r--drivers/acpi/blacklist.c21
-rw-r--r--drivers/acpi/bus.c5
-rw-r--r--drivers/acpi/cm_sbs.c105
-rw-r--r--drivers/acpi/ec.c21
-rw-r--r--drivers/acpi/thermal.c2
-rw-r--r--drivers/acpi/video.c16
-rw-r--r--drivers/ata/Kconfig7
-rw-r--r--drivers/ata/ahci.c50
-rw-r--r--drivers/ata/ahci.h2
-rw-r--r--drivers/ata/ahci_imx.c179
-rw-r--r--drivers/ata/libahci.c7
-rw-r--r--drivers/ata/libata-core.c36
-rw-r--r--drivers/ata/pata_arasan_cf.c7
-rw-r--r--drivers/ata/pata_at91.c11
-rw-r--r--drivers/ata/pata_samsung_cf.c10
-rw-r--r--drivers/base/core.c33
-rw-r--r--drivers/base/dd.c21
-rw-r--r--drivers/base/platform.c7
-rw-r--r--drivers/base/topology.c3
-rw-r--r--drivers/block/ataflop.c2
-rw-r--r--drivers/block/floppy.c11
-rw-r--r--drivers/block/virtio_blk.c4
-rw-r--r--drivers/bluetooth/ath3k.c2
-rw-r--r--drivers/bluetooth/btusb.c5
-rw-r--r--drivers/bus/mvebu-mbus.c22
-rw-r--r--drivers/char/Kconfig2
-rw-r--r--drivers/char/agp/frontend.c1
-rw-r--r--drivers/char/hw_random/bcm2835-rng.c10
-rw-r--r--drivers/char/ipmi/Kconfig12
-rw-r--r--drivers/char/ipmi/ipmi_bt_sm.c2
-rw-r--r--drivers/char/ipmi/ipmi_kcs_sm.c5
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c239
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c145
-rw-r--r--drivers/char/pcmcia/Kconfig2
-rw-r--r--drivers/char/random.c7
-rw-r--r--drivers/char/tpm/tpm_ppi.c8
-rw-r--r--drivers/char/ttyprintk.c15
-rw-r--r--drivers/clk/bcm/clk-kona-setup.c33
-rw-r--r--drivers/clk/bcm/clk-kona.c64
-rw-r--r--drivers/clk/bcm/clk-kona.h28
-rw-r--r--drivers/clk/clk-divider.c37
-rw-r--r--drivers/clk/clk.c74
-rw-r--r--drivers/clk/shmobile/clk-mstp.c9
-rw-r--r--drivers/clk/socfpga/clk-pll.c7
-rw-r--r--drivers/clk/socfpga/clk.c23
-rw-r--r--drivers/clk/st/clkgen-pll.c4
-rw-r--r--drivers/clk/tegra/clk-pll.c66
-rw-r--r--drivers/clk/tegra/clk-tegra124.c3
-rw-r--r--drivers/clk/versatile/clk-vexpress-osc.c4
-rw-r--r--drivers/clocksource/arm_arch_timer.c6
-rw-r--r--drivers/clocksource/exynos_mct.c12
-rw-r--r--drivers/clocksource/tcb_clksrc.c8
-rw-r--r--drivers/clocksource/timer-marco.c2
-rw-r--r--drivers/clocksource/zevio-timer.c7
-rw-r--r--drivers/connector/cn_proc.c2
-rw-r--r--drivers/cpufreq/Kconfig.arm6
-rw-r--r--drivers/cpufreq/cpufreq-cpu0.c16
-rw-r--r--drivers/cpufreq/cpufreq_governor.c6
-rw-r--r--drivers/cpufreq/intel_pstate.c34
-rw-r--r--drivers/cpufreq/longhaul.c36
-rw-r--r--drivers/cpufreq/loongson2_cpufreq.c4
-rw-r--r--drivers/cpufreq/powernow-k6.c23
-rw-r--r--drivers/cpufreq/powernow-k7.c4
-rw-r--r--drivers/cpufreq/powernv-cpufreq.c1
-rw-r--r--drivers/cpufreq/ppc-corenet-cpufreq.c5
-rw-r--r--drivers/cpufreq/unicore2-cpufreq.c4
-rw-r--r--drivers/crypto/caam/error.c10
-rw-r--r--drivers/dma/Kconfig2
-rw-r--r--drivers/dma/dmaengine.c2
-rw-r--r--drivers/dma/dw/core.c11
-rw-r--r--drivers/dma/edma.c6
-rw-r--r--drivers/dma/fsl-edma.c12
-rw-r--r--drivers/dma/mv_xor.c8
-rw-r--r--drivers/dma/sa11x0-dma.c4
-rw-r--r--drivers/dma/sirf-dma.c2
-rw-r--r--drivers/edac/edac_mc.c2
-rw-r--r--drivers/edac/mce_amd.c2
-rw-r--r--drivers/firewire/core.h4
-rw-r--r--drivers/firewire/ohci.c2
-rw-r--r--drivers/firmware/iscsi_ibft.c1
-rw-r--r--drivers/gpio/Kconfig20
-rw-r--r--drivers/gpio/Makefile2
-rw-r--r--drivers/gpio/devres.c43
-rw-r--r--drivers/gpio/gpio-adp5520.c4
-rw-r--r--drivers/gpio/gpio-adp5588.c4
-rw-r--r--drivers/gpio/gpio-bt8xx.c19
-rw-r--r--drivers/gpio/gpio-davinci.c4
-rw-r--r--drivers/gpio/gpio-dwapb.c38
-rw-r--r--drivers/gpio/gpio-em.c3
-rw-r--r--drivers/gpio/gpio-ep93xx.c34
-rw-r--r--drivers/gpio/gpio-ge.c174
-rw-r--r--drivers/gpio/gpio-generic.c9
-rw-r--r--drivers/gpio/gpio-grgpio.c2
-rw-r--r--drivers/gpio/gpio-ich.c4
-rw-r--r--drivers/gpio/gpio-janz-ttl.c38
-rw-r--r--drivers/gpio/gpio-kempld.c4
-rw-r--r--drivers/gpio/gpio-lynxpoint.c4
-rw-r--r--drivers/gpio/gpio-max730x.c5
-rw-r--r--drivers/gpio/gpio-mcp23s08.c23
-rw-r--r--drivers/gpio/gpio-moxart.c4
-rw-r--r--drivers/gpio/gpio-mvebu.c13
-rw-r--r--drivers/gpio/gpio-omap.c205
-rw-r--r--drivers/gpio/gpio-palmas.c6
-rw-r--r--drivers/gpio/gpio-pca953x.c102
-rw-r--r--drivers/gpio/gpio-pcf857x.c11
-rw-r--r--drivers/gpio/gpio-pch.c1
-rw-r--r--drivers/gpio/gpio-pl061.c27
-rw-r--r--drivers/gpio/gpio-rc5t583.c4
-rw-r--r--drivers/gpio/gpio-rcar.c9
-rw-r--r--drivers/gpio/gpio-rdc321x.c23
-rw-r--r--drivers/gpio/gpio-sch.c26
-rw-r--r--drivers/gpio/gpio-sch311x.c16
-rw-r--r--drivers/gpio/gpio-spear-spics.c8
-rw-r--r--drivers/gpio/gpio-sx150x.c1
-rw-r--r--drivers/gpio/gpio-tc3589x.c148
-rw-r--r--drivers/gpio/gpio-tegra.c6
-rw-r--r--drivers/gpio/gpio-timberdale.c47
-rw-r--r--drivers/gpio/gpio-tps6586x.c4
-rw-r--r--drivers/gpio/gpio-tps65910.c4
-rw-r--r--drivers/gpio/gpio-xilinx.c2
-rw-r--r--drivers/gpio/gpio-zevio.c18
-rw-r--r--drivers/gpio/gpiolib-acpi.c15
-rw-r--r--drivers/gpio/gpiolib-of.c16
-rw-r--r--drivers/gpio/gpiolib.c103
-rw-r--r--drivers/gpio/gpiolib.h5
-rw-r--r--drivers/gpu/drm/Makefile2
-rw-r--r--drivers/gpu/drm/ast/ast_post.c2
-rw-r--r--drivers/gpu/drm/bochs/bochs.h3
-rw-r--r--drivers/gpu/drm/bochs/bochs_drv.c44
-rw-r--r--drivers/gpu/drm/bochs/bochs_fbdev.c1
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_drv.c42
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_mode.c3
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c370
-rw-r--r--drivers/gpu/drm/drm_dp_helper.c55
-rw-r--r--drivers/gpu/drm/drm_mm.c2
-rw-r--r--drivers/gpu/drm/drm_plane_helper.c33
-rw-r--r--drivers/gpu/drm/drm_probe_helper.c426
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.c1
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_dmabuf.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_dsi.c4
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_vidi.c2
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c1
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h42
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c367
-rw-r--r--drivers/gpu/drm/i915/i915_gem_context.c218
-rw-r--r--drivers/gpu/drm/i915/i915_gem_evict.c9
-rw-r--r--drivers/gpu/drm/i915/i915_gem_execbuffer.c132
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.c36
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c18
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h1
-rw-r--r--drivers/gpu/drm/i915/intel_bios.c62
-rw-r--r--drivers/gpu/drm/i915/intel_bios.h3
-rw-r--r--drivers/gpu/drm/i915/intel_display.c60
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c76
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h3
-rw-r--r--drivers/gpu/drm/i915/intel_fbdev.c19
-rw-r--r--drivers/gpu/drm/i915/intel_hdmi.c9
-rw-r--r--drivers/gpu/drm/i915/intel_overlay.c12
-rw-r--r--drivers/gpu/drm/i915/intel_panel.c13
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c50
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c54
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.h1
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c4
-rw-r--r--drivers/gpu/drm/i915/intel_uncore.c2
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c9
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c4
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c21
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h4
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c4
-rw-r--r--drivers/gpu/drm/msm/msm_fbdev.c5
-rw-r--r--drivers/gpu/drm/msm/msm_gem.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bios/base.c12
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_acpi.c3
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c2
-rw-r--r--drivers/gpu/drm/omapdrm/omap_crtc.c100
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.c32
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.h1
-rw-r--r--drivers/gpu/drm/omapdrm/omap_fb.c14
-rw-r--r--drivers/gpu/drm/omapdrm/omap_fbdev.c3
-rw-r--r--drivers/gpu/drm/omapdrm/omap_gem.c9
-rw-r--r--drivers/gpu/drm/omapdrm/omap_plane.c16
-rw-r--r--drivers/gpu/drm/radeon/atombios_crtc.c54
-rw-r--r--drivers/gpu/drm/radeon/atombios_dp.c175
-rw-r--r--drivers/gpu/drm/radeon/ci_dpm.c33
-rw-r--r--drivers/gpu/drm/radeon/cik.c176
-rw-r--r--drivers/gpu/drm/radeon/cik_sdma.c3
-rw-r--r--drivers/gpu/drm/radeon/cikd.h9
-rw-r--r--drivers/gpu/drm/radeon/dce6_afmt.c14
-rw-r--r--drivers/gpu/drm/radeon/evergreen.c28
-rw-r--r--drivers/gpu/drm/radeon/evergreen_dma.c1
-rw-r--r--drivers/gpu/drm/radeon/kv_dpm.c135
-rw-r--r--drivers/gpu/drm/radeon/r600.c14
-rw-r--r--drivers/gpu/drm/radeon/r600_dma.c1
-rw-r--r--drivers/gpu/drm/radeon/r600_dpm.c35
-rw-r--r--drivers/gpu/drm/radeon/radeon.h16
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.c1
-rw-r--r--drivers/gpu/drm/radeon/radeon_atpx_handler.c9
-rw-r--r--drivers/gpu/drm/radeon/radeon_bios.c14
-rw-r--r--drivers/gpu/drm/radeon/radeon_connectors.c44
-rw-r--r--drivers/gpu/drm/radeon/radeon_cs.c21
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c31
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c111
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.c26
-rw-r--r--drivers/gpu/drm/radeon/radeon_family.h2
-rw-r--r--drivers/gpu/drm/radeon/radeon_i2c.c60
-rw-r--r--drivers/gpu/drm/radeon/radeon_kms.c68
-rw-r--r--drivers/gpu/drm/radeon/radeon_mode.h12
-rw-r--r--drivers/gpu/drm/radeon/radeon_object.c40
-rw-r--r--drivers/gpu/drm/radeon/radeon_pm.c94
-rw-r--r--drivers/gpu/drm/radeon/radeon_ucode.h8
-rw-r--r--drivers/gpu/drm/radeon/radeon_uvd.c5
-rw-r--r--drivers/gpu/drm/radeon/radeon_vce.c133
-rw-r--r--drivers/gpu/drm/radeon/radeon_vm.c8
-rw-r--r--drivers/gpu/drm/radeon/rv770_dma.c1
-rw-r--r--drivers/gpu/drm/radeon/si.c65
-rw-r--r--drivers/gpu/drm/radeon/si_dma.c1
-rw-r--r--drivers/gpu/drm/radeon/sid.h4
-rw-r--r--drivers/gpu/drm/radeon/uvd_v1_0.c10
-rw-r--r--drivers/gpu/drm/tegra/dc.c2
-rw-r--r--drivers/gpu/drm/tegra/dpaux.c44
-rw-r--r--drivers/gpu/drm/tegra/dpaux.h1
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c22
-rw-r--r--drivers/gpu/host1x/hw/intr_hw.c4
-rw-r--r--drivers/hid/hid-core.c10
-rw-r--r--drivers/hid/hid-ids.h12
-rw-r--r--drivers/hid/hid-microsoft.c4
-rw-r--r--drivers/hid/hid-multitouch.c5
-rw-r--r--drivers/hid/hid-sensor-hub.c10
-rw-r--r--drivers/hid/hid-sony.c2
-rw-r--r--drivers/hid/usbhid/hid-quirks.c1
-rw-r--r--drivers/hsi/Kconfig1
-rw-r--r--drivers/hsi/Makefile1
-rw-r--r--drivers/hsi/clients/Kconfig17
-rw-r--r--drivers/hsi/clients/Makefile4
-rw-r--r--drivers/hsi/clients/hsi_char.c14
-rw-r--r--drivers/hsi/clients/nokia-modem.c285
-rw-r--r--drivers/hsi/clients/ssi_protocol.c1191
-rw-r--r--drivers/hsi/controllers/Kconfig19
-rw-r--r--drivers/hsi/controllers/Makefile6
-rw-r--r--drivers/hsi/controllers/omap_ssi.c625
-rw-r--r--drivers/hsi/controllers/omap_ssi.h166
-rw-r--r--drivers/hsi/controllers/omap_ssi_port.c1399
-rw-r--r--drivers/hsi/controllers/omap_ssi_regs.h171
-rw-r--r--drivers/hsi/hsi.c275
-rw-r--r--drivers/hv/connection.c5
-rw-r--r--drivers/hwmon/Kconfig2
-rw-r--r--drivers/hwmon/coretemp.c4
-rw-r--r--drivers/hwmon/emc1403.c10
-rw-r--r--drivers/hwmon/ltc2945.c6
-rw-r--r--drivers/hwmon/ntc_thermistor.c15
-rw-r--r--drivers/hwmon/vexpress.c83
-rw-r--r--drivers/i2c/busses/i2c-designware-core.c3
-rw-r--r--drivers/i2c/busses/i2c-nomadik.c2
-rw-r--r--drivers/i2c/busses/i2c-qup.c2
-rw-r--r--drivers/i2c/busses/i2c-rcar.c9
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c2
-rw-r--r--drivers/idle/intel_idle.c3
-rw-r--r--drivers/iio/adc/Kconfig4
-rw-r--r--drivers/iio/adc/at91_adc.c33
-rw-r--r--drivers/iio/adc/exynos_adc.c6
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_core.c7
-rw-r--r--drivers/iio/industrialio-buffer.c6
-rw-r--r--drivers/iio/light/cm32181.c1
-rw-r--r--drivers/iio/light/cm36651.c22
-rw-r--r--drivers/infiniband/hw/cxgb4/Kconfig6
-rw-r--r--drivers/infiniband/hw/cxgb4/cm.c128
-rw-r--r--drivers/infiniband/hw/cxgb4/cq.c24
-rw-r--r--drivers/infiniband/hw/cxgb4/device.c41
-rw-r--r--drivers/infiniband/hw/cxgb4/iw_cxgb4.h3
-rw-r--r--drivers/infiniband/hw/cxgb4/mem.c6
-rw-r--r--drivers/infiniband/hw/cxgb4/provider.c2
-rw-r--r--drivers/infiniband/hw/cxgb4/qp.c81
-rw-r--r--drivers/infiniband/hw/cxgb4/resource.c10
-rw-r--r--drivers/infiniband/hw/cxgb4/t4.h72
-rw-r--r--drivers/infiniband/hw/cxgb4/t4fw_ri_api.h14
-rw-r--r--drivers/infiniband/hw/mlx4/main.c67
-rw-r--r--drivers/infiniband/hw/mlx4/mlx4_ib.h3
-rw-r--r--drivers/infiniband/hw/mlx4/qp.c8
-rw-r--r--drivers/infiniband/hw/mlx5/main.c2
-rw-r--r--drivers/infiniband/hw/mlx5/qp.c12
-rw-r--r--drivers/infiniband/hw/mthca/mthca_main.c8
-rw-r--r--drivers/infiniband/hw/qib/qib_pcie.c55
-rw-r--r--drivers/infiniband/ulp/isert/ib_isert.c38
-rw-r--r--drivers/infiniband/ulp/isert/ib_isert.h2
-rw-r--r--drivers/input/keyboard/Kconfig2
-rw-r--r--drivers/input/keyboard/atkbd.c29
-rw-r--r--drivers/input/keyboard/pxa27x_keypad.c7
-rw-r--r--drivers/input/keyboard/tca8418_keypad.c7
-rw-r--r--drivers/input/misc/bma150.c4
-rw-r--r--drivers/input/misc/da9055_onkey.c1
-rw-r--r--drivers/input/misc/soc_button_array.c1
-rw-r--r--drivers/input/mouse/Kconfig2
-rw-r--r--drivers/input/mouse/elantech.c27
-rw-r--r--drivers/input/mouse/elantech.h1
-rw-r--r--drivers/input/mouse/synaptics.c145
-rw-r--r--drivers/input/serio/ambakmi.c3
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h15
-rw-r--r--drivers/input/serio/i8042.c6
-rw-r--r--drivers/input/serio/serio.c14
-rw-r--r--drivers/input/tablet/wacom_sys.c246
-rw-r--r--drivers/input/tablet/wacom_wac.c29
-rw-r--r--drivers/input/touchscreen/Kconfig2
-rw-r--r--drivers/input/touchscreen/ads7846.c2
-rw-r--r--drivers/iommu/amd_iommu.c2
-rw-r--r--drivers/iommu/amd_iommu_init.c2
-rw-r--r--drivers/iommu/amd_iommu_v2.c2
-rw-r--r--drivers/iommu/arm-smmu.c4
-rw-r--r--drivers/iommu/dmar.c3
-rw-r--r--drivers/iommu/intel-iommu.c10
-rw-r--r--drivers/irqchip/irq-armada-370-xp.c54
-rw-r--r--drivers/irqchip/irq-crossbar.c2
-rw-r--r--drivers/irqchip/irq-gic.c8
-rw-r--r--drivers/irqchip/irq-vic.c6
-rw-r--r--drivers/irqchip/spear-shirq.c2
-rw-r--r--drivers/isdn/hisax/icc.c2
-rw-r--r--drivers/isdn/icn/icn.c11
-rw-r--r--drivers/mcb/mcb-parse.c1
-rw-r--r--drivers/md/dm-cache-target.c3
-rw-r--r--drivers/md/dm-crypt.c61
-rw-r--r--drivers/md/dm-mpath.c12
-rw-r--r--drivers/md/dm-thin.c106
-rw-r--r--drivers/md/dm-verity.c15
-rw-r--r--drivers/md/md.c3
-rw-r--r--drivers/md/raid10.c13
-rw-r--r--drivers/md/raid5.c3
-rw-r--r--drivers/media/i2c/ov7670.c2
-rw-r--r--drivers/media/i2c/s5c73m3/s5c73m3-core.c2
-rw-r--r--drivers/media/media-device.c1
-rw-r--r--drivers/media/platform/Kconfig2
-rw-r--r--drivers/media/platform/davinci/vpbe_display.c16
-rw-r--r--drivers/media/platform/davinci/vpfe_capture.c2
-rw-r--r--drivers/media/platform/davinci/vpif_capture.c34
-rw-r--r--drivers/media/platform/davinci/vpif_display.c35
-rw-r--r--drivers/media/platform/exynos4-is/fimc-core.c2
-rw-r--r--drivers/media/tuners/fc2580.c6
-rw-r--r--drivers/media/tuners/fc2580_priv.h1
-rw-r--r--drivers/media/usb/dvb-usb-v2/Makefile1
-rw-r--r--drivers/media/usb/dvb-usb-v2/rtl28xxu.c48
-rw-r--r--drivers/media/usb/gspca/sonixb.c2
-rw-r--r--drivers/media/v4l2-core/v4l2-compat-ioctl32.c12
-rw-r--r--drivers/memory/mvebu-devbus.c15
-rw-r--r--drivers/mfd/rtsx_pcr.c132
-rw-r--r--drivers/misc/Kconfig4
-rw-r--r--drivers/misc/genwqe/card_base.h58
-rw-r--r--drivers/misc/genwqe/card_ddcb.c6
-rw-r--r--drivers/misc/genwqe/card_dev.c44
-rw-r--r--drivers/misc/genwqe/card_utils.c170
-rw-r--r--drivers/misc/genwqe/genwqe_driver.h2
-rw-r--r--drivers/misc/mei/hw-me-regs.h5
-rw-r--r--drivers/misc/mei/interrupt.c3
-rw-r--r--drivers/misc/mei/main.c3
-rw-r--r--drivers/misc/mei/pci-me.c30
-rw-r--r--drivers/mmc/host/mmci.c324
-rw-r--r--drivers/mmc/host/mmci.h14
-rw-r--r--drivers/mmc/host/rtsx_pci_sdmmc.c418
-rw-r--r--drivers/mtd/devices/spear_smi.c4
-rw-r--r--drivers/mtd/nand/davinci_nand.c6
-rw-r--r--drivers/mtd/ubi/block.c2
-rw-r--r--drivers/mtd/ubi/wl.c6
-rw-r--r--drivers/net/bonding/bond_alb.c54
-rw-r--r--drivers/net/bonding/bond_main.c134
-rw-r--r--drivers/net/bonding/bond_options.c1
-rw-r--r--drivers/net/bonding/bond_sysfs.c2
-rw-r--r--drivers/net/bonding/bonding.h1
-rw-r--r--drivers/net/can/c_can/c_can.c648
-rw-r--r--drivers/net/can/c_can/c_can.h23
-rw-r--r--drivers/net/can/c_can/c_can_pci.c9
-rw-r--r--drivers/net/can/c_can/c_can_platform.c2
-rw-r--r--drivers/net/can/dev.c2
-rw-r--r--drivers/net/can/sja1000/peak_pci.c14
-rw-r--r--drivers/net/can/sja1000/sja1000_isa.c16
-rw-r--r--drivers/net/can/slcan.c6
-rw-r--r--drivers/net/ethernet/Kconfig12
-rw-r--r--drivers/net/ethernet/Makefile1
-rw-r--r--drivers/net/ethernet/altera/Kconfig1
-rw-r--r--drivers/net/ethernet/altera/Makefile1
-rw-r--r--drivers/net/ethernet/altera/altera_msgdma.c118
-rw-r--r--drivers/net/ethernet/altera/altera_msgdma.h3
-rw-r--r--drivers/net/ethernet/altera/altera_msgdmahw.h13
-rw-r--r--drivers/net/ethernet/altera/altera_sgdma.c338
-rw-r--r--drivers/net/ethernet/altera/altera_sgdma.h3
-rw-r--r--drivers/net/ethernet/altera/altera_sgdmahw.h26
-rw-r--r--drivers/net/ethernet/altera/altera_tse.h53
-rw-r--r--drivers/net/ethernet/altera/altera_tse_ethtool.c116
-rw-r--r--drivers/net/ethernet/altera/altera_tse_main.c206
-rw-r--r--drivers/net/ethernet/altera/altera_utils.c20
-rw-r--r--drivers/net/ethernet/altera/altera_utils.h8
-rw-r--r--drivers/net/ethernet/arc/emac.h2
-rw-r--r--drivers/net/ethernet/arc/emac_main.c82
-rw-r--r--drivers/net/ethernet/broadcom/bnx2.c2
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c12
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c60
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h4
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c4
-rw-r--r--drivers/net/ethernet/broadcom/tg3.c4
-rw-r--r--drivers/net/ethernet/cadence/Kconfig6
-rw-r--r--drivers/net/ethernet/cadence/macb.c35
-rw-r--r--drivers/net/ethernet/chelsio/Kconfig13
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/l2t.c4
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_hw.c2
-rw-r--r--drivers/net/ethernet/ec_bhf.c706
-rw-r--r--drivers/net/ethernet/emulex/benet/be.h1
-rw-r--r--drivers/net/ethernet/emulex/benet/be_main.c23
-rw-r--r--drivers/net/ethernet/freescale/gianfar.c223
-rw-r--r--drivers/net/ethernet/freescale/gianfar_ethtool.c3
-rw-r--r--drivers/net/ethernet/intel/e1000e/ich8lan.c71
-rw-r--r--drivers/net/ethernet/intel/e1000e/ich8lan.h3
-rw-r--r--drivers/net/ethernet/intel/e1000e/netdev.c6
-rw-r--r--drivers/net/ethernet/intel/e1000e/phy.h1
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_main.c14
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_nvm.c2
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_ptp.c4
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_txrx.c22
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_i210.c2
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_mac.c13
-rw-r--r--drivers/net/ethernet/intel/igb/igb_main.c4
-rw-r--r--drivers/net/ethernet/intel/igb/igb_ptp.c4
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe.h21
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_common.c2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c3
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c6
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c40
-rw-r--r--drivers/net/ethernet/jme.c53
-rw-r--r--drivers/net/ethernet/marvell/mvmdio.c5
-rw-r--r--drivers/net/ethernet/marvell/mvneta.c46
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/cmd.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_cq.c1
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_netdev.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/main.c188
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4.h7
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4_en.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/port.c35
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/qp.c35
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/resource_tracker.c77
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic.h16
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c21
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c3
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c2
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c99
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c9
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c10
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c31
-rw-r--r--drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h2
-rw-r--r--drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c22
-rw-r--r--drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.c11
-rw-r--r--drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.h42
-rw-r--r--drivers/net/ethernet/samsung/sxgbe/sxgbe_dma.c13
-rw-r--r--drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c31
-rw-r--r--drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c14
-rw-r--r--drivers/net/ethernet/samsung/sxgbe/sxgbe_reg.h4
-rw-r--r--drivers/net/ethernet/sfc/ef10.c12
-rw-r--r--drivers/net/ethernet/sfc/efx.c19
-rw-r--r--drivers/net/ethernet/sfc/enum.h23
-rw-r--r--drivers/net/ethernet/sfc/falcon.c4
-rw-r--r--drivers/net/ethernet/sfc/farch.c22
-rw-r--r--drivers/net/ethernet/sfc/mcdi.c55
-rw-r--r--drivers/net/ethernet/sfc/mcdi.h13
-rw-r--r--drivers/net/ethernet/sfc/net_driver.h4
-rw-r--r--drivers/net/ethernet/sfc/nic.c14
-rw-r--r--drivers/net/ethernet/sfc/nic.h1
-rw-r--r--drivers/net/ethernet/sfc/siena.c2
-rw-r--r--drivers/net/ethernet/smsc/smc91x.c25
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c4
-rw-r--r--drivers/net/ethernet/sun/cassini.c2
-rw-r--r--drivers/net/ethernet/ti/cpsw.c17
-rw-r--r--drivers/net/hyperv/netvsc_drv.c4
-rw-r--r--drivers/net/ieee802154/at86rf230.c10
-rw-r--r--drivers/net/macvlan.c21
-rw-r--r--drivers/net/macvtap.c9
-rw-r--r--drivers/net/phy/mdio-gpio.c72
-rw-r--r--drivers/net/phy/micrel.c6
-rw-r--r--drivers/net/phy/phy.c27
-rw-r--r--drivers/net/phy/phy_device.c4
-rw-r--r--drivers/net/slip/slip.c6
-rw-r--r--drivers/net/team/team.c2
-rw-r--r--drivers/net/usb/cdc_mbim.c57
-rw-r--r--drivers/net/usb/cdc_ncm.c2
-rw-r--r--drivers/net/usb/qmi_wwan.c28
-rw-r--r--drivers/net/virtio_net.c2
-rw-r--r--drivers/net/vxlan.c42
-rw-r--r--drivers/net/wan/cosa.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/ahb.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/ani.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/debug_sta.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/pci.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c9
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c14
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/chip.c5
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c2
-rw-r--r--drivers/net/wireless/cw1200/debug.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-7000.c5
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/coex.c24
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h8
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c10
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mvm.h3
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rs.c261
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rs.h14
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/scan.c55
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/sf.c3
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/utils.c19
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/drv.c2
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/trans.c10
-rw-r--r--drivers/net/wireless/mwifiex/main.c12
-rw-r--r--drivers/net/wireless/mwifiex/sta_ioctl.c7
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_core.c2
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_mgmt.c21
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c22
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8188ee/trx.c2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/hw.c2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/trx.c6
-rw-r--r--drivers/net/wireless/ti/wl18xx/event.h20
-rw-r--r--drivers/net/wireless/ti/wlcore/event.c5
-rw-r--r--drivers/net/xen-netback/common.h2
-rw-r--r--drivers/net/xen-netback/interface.c30
-rw-r--r--drivers/net/xen-netback/netback.c102
-rw-r--r--drivers/of/base.c14
-rw-r--r--drivers/of/fdt.c2
-rw-r--r--drivers/of/irq.c28
-rw-r--r--drivers/of/platform.c4
-rw-r--r--drivers/of/selftest.c32
-rw-r--r--drivers/of/testcase-data/tests-interrupts.dtsi13
-rw-r--r--drivers/pci/host/pci-mvebu.c92
-rw-r--r--drivers/pci/host/pci-rcar-gen2.c8
-rw-r--r--drivers/pci/host/pci-tegra.c7
-rw-r--r--drivers/pci/host/pcie-designware.c20
-rw-r--r--drivers/pci/hotplug/shpchp_ctrl.c4
-rw-r--r--drivers/pci/pci.c5
-rw-r--r--drivers/phy/Kconfig1
-rw-r--r--drivers/phy/Makefile9
-rw-r--r--drivers/phy/phy-core.c3
-rw-r--r--drivers/pinctrl/Kconfig8
-rw-r--r--drivers/pinctrl/Makefile2
-rw-r--r--drivers/pinctrl/pinctrl-as3722.c17
-rw-r--r--drivers/pinctrl/pinctrl-bcm281xx.c1461
-rw-r--r--drivers/pinctrl/pinctrl-capri.c1454
-rw-r--r--drivers/pinctrl/pinctrl-msm.c6
-rw-r--r--drivers/pinctrl/pinctrl-msm.h1
-rw-r--r--drivers/pinctrl/pinctrl-nomadik.c1
-rw-r--r--drivers/pinctrl/pinctrl-rockchip.c48
-rw-r--r--drivers/pinctrl/pinctrl-single.c13
-rw-r--r--drivers/pinctrl/pinctrl-tb10x.c3
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7790.c3
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7791.c2
-rw-r--r--drivers/pinctrl/vt8500/pinctrl-wmt.c23
-rw-r--r--drivers/pnp/pnpacpi/core.c44
-rw-r--r--drivers/pnp/pnpbios/bioscalls.c2
-rw-r--r--drivers/pnp/quirks.c79
-rw-r--r--drivers/power/reset/vexpress-poweroff.c19
-rw-r--r--drivers/ptp/Kconfig3
-rw-r--r--drivers/pwm/pwm-spear.c4
-rw-r--r--drivers/regulator/pbias-regulator.c76
-rw-r--r--drivers/rtc/rtc-hym8563.c3
-rw-r--r--drivers/rtc/rtc-pcf8523.c4
-rw-r--r--drivers/s390/char/sclp.c2
-rw-r--r--drivers/s390/char/sclp_cmd.c2
-rw-r--r--drivers/s390/char/sclp_vt220.c14
-rw-r--r--drivers/s390/cio/chsc.c22
-rw-r--r--drivers/scsi/atari_scsi.c2
-rw-r--r--drivers/scsi/hpsa.c8
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c1
-rw-r--r--drivers/scsi/scsi_error.c12
-rw-r--r--drivers/scsi/scsi_lib.c6
-rw-r--r--drivers/scsi/scsi_netlink.c2
-rw-r--r--drivers/scsi/scsi_transport_sas.c3
-rw-r--r--drivers/scsi/virtio_scsi.c6
-rw-r--r--drivers/sh/Makefile14
-rw-r--r--drivers/sh/pm_runtime.c20
-rw-r--r--drivers/spi/spi-atmel.c3
-rw-r--r--drivers/spi/spi-bfin5xx.c1
-rw-r--r--drivers/spi/spi-pxa2xx-dma.c16
-rw-r--r--drivers/spi/spi-qup.c2
-rw-r--r--drivers/spi/spi-sh-hspi.c4
-rw-r--r--drivers/spi/spi-sirf.c20
-rw-r--r--drivers/spi/spi.c124
-rw-r--r--drivers/staging/Kconfig2
-rw-r--r--drivers/staging/Makefile1
-rw-r--r--drivers/staging/comedi/comedi_buf.c37
-rw-r--r--drivers/staging/comedi/comedi_fops.c18
-rw-r--r--drivers/staging/comedi/comedi_internal.h2
-rw-r--r--drivers/staging/comedi/drivers/usbdux.c9
-rw-r--r--drivers/staging/goldfish/goldfish_audio.c1
-rw-r--r--drivers/staging/gs_fpgaboot/Makefile2
-rw-r--r--drivers/staging/gs_fpgaboot/gs_fpgaboot.c1
-rw-r--r--drivers/staging/iio/adc/mxs-lradc.c2
-rw-r--r--drivers/staging/iio/resolver/ad2s1200.c4
-rw-r--r--drivers/staging/imx-drm/imx-drm-core.c7
-rw-r--r--drivers/staging/imx-drm/imx-tve.c2
-rw-r--r--drivers/staging/media/davinci_vpfe/vpfe_video.c13
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_devtable.h2
-rw-r--r--drivers/staging/rtl8187se/Kconfig10
-rw-r--r--drivers/staging/rtl8187se/Makefile38
-rw-r--r--drivers/staging/rtl8187se/Module.symvers0
-rw-r--r--drivers/staging/rtl8187se/TODO13
-rw-r--r--drivers/staging/rtl8187se/ieee80211/dot11d.c189
-rw-r--r--drivers/staging/rtl8187se/ieee80211/dot11d.h71
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211.h1496
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c240
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.h86
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c455
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c740
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_wep.c277
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_module.c203
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c1486
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c2711
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c567
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c591
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c713
-rw-r--r--drivers/staging/rtl8187se/r8180.h640
-rw-r--r--drivers/staging/rtl8187se/r8180_93cx6.h54
-rw-r--r--drivers/staging/rtl8187se/r8180_core.c3775
-rw-r--r--drivers/staging/rtl8187se/r8180_dm.c1139
-rw-r--r--drivers/staging/rtl8187se/r8180_dm.h23
-rw-r--r--drivers/staging/rtl8187se/r8180_hw.h588
-rw-r--r--drivers/staging/rtl8187se/r8180_rtl8225.h34
-rw-r--r--drivers/staging/rtl8187se/r8180_rtl8225z2.c811
-rw-r--r--drivers/staging/rtl8187se/r8180_wx.c1409
-rw-r--r--drivers/staging/rtl8187se/r8180_wx.h21
-rw-r--r--drivers/staging/rtl8187se/r8185b_init.c1464
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_recv.c19
-rw-r--r--drivers/staging/rtl8188eu/os_dep/ioctl_linux.c74
-rw-r--r--drivers/staging/rtl8712/rtl871x_recv.c13
-rw-r--r--drivers/staging/rtl8723au/core/rtw_ieee80211.c46
-rw-r--r--drivers/staging/rtl8723au/core/rtw_mlme_ext.c2
-rw-r--r--drivers/staging/rtl8723au/core/rtw_p2p.c4
-rw-r--r--drivers/staging/rtl8723au/core/rtw_wlan_util.c4
-rw-r--r--drivers/staging/rtl8723au/os_dep/os_intfs.c2
-rw-r--r--drivers/staging/rtl8723au/os_dep/usb_ops_linux.c2
-rw-r--r--drivers/staging/rtl8821ae/base.c10
-rw-r--r--drivers/staging/speakup/main.c18
-rw-r--r--drivers/staging/unisys/uislib/uislib.c4
-rw-r--r--drivers/staging/unisys/visorchipset/visorchipset.h4
-rw-r--r--drivers/staging/unisys/visorchipset/visorchipset_main.c8
-rw-r--r--drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c7
-rw-r--r--drivers/staging/usbip/vhci_sysfs.c2
-rw-r--r--drivers/staging/vme/devices/vme_user.c9
-rw-r--r--drivers/staging/xgifb/vb_def.h2
-rw-r--r--drivers/staging/xgifb/vb_struct.h2
-rw-r--r--drivers/staging/xgifb/vgatypes.h4
-rw-r--r--drivers/target/iscsi/iscsi_target.c4
-rw-r--r--drivers/target/iscsi/iscsi_target_core.h1
-rw-r--r--drivers/target/iscsi/iscsi_target_login.c28
-rw-r--r--drivers/target/iscsi/iscsi_target_tpg.c1
-rw-r--r--drivers/target/target_core_device.c12
-rw-r--r--drivers/target/target_core_transport.c2
-rw-r--r--drivers/target/tcm_fc/tfc_cmd.c8
-rw-r--r--drivers/tty/hvc/hvc_console.c2
-rw-r--r--drivers/tty/n_tty.c4
-rw-r--r--drivers/tty/serial/8250/8250_core.c4
-rw-r--r--drivers/tty/serial/8250/8250_dma.c9
-rw-r--r--drivers/tty/serial/Kconfig1
-rw-r--r--drivers/tty/serial/amba-pl011.c8
-rw-r--r--drivers/tty/serial/clps711x.c20
-rw-r--r--drivers/tty/serial/efm32-uart.c3
-rw-r--r--drivers/tty/serial/omap-serial.c30
-rw-r--r--drivers/tty/serial/samsung.c23
-rw-r--r--drivers/tty/serial/serial_core.c44
-rw-r--r--drivers/tty/serial/st-asc.c4
-rw-r--r--drivers/tty/tty_buffer.c17
-rw-r--r--drivers/tty/tty_io.c4
-rw-r--r--drivers/usb/chipidea/core.c37
-rw-r--r--drivers/usb/class/cdc-acm.c34
-rw-r--r--drivers/usb/core/hcd-pci.c2
-rw-r--r--drivers/usb/dwc3/core.c2
-rw-r--r--drivers/usb/dwc3/gadget.c12
-rw-r--r--drivers/usb/gadget/at91_udc.c10
-rw-r--r--drivers/usb/gadget/f_fs.c7
-rw-r--r--drivers/usb/gadget/f_rndis.c2
-rw-r--r--drivers/usb/gadget/fsl_udc_core.c6
-rw-r--r--drivers/usb/gadget/inode.c1
-rw-r--r--drivers/usb/gadget/rndis.c1
-rw-r--r--drivers/usb/gadget/u_ether.c101
-rw-r--r--drivers/usb/gadget/zero.c2
-rw-r--r--drivers/usb/host/ehci-exynos.c2
-rw-r--r--drivers/usb/host/ehci-fsl.c3
-rw-r--r--drivers/usb/host/ehci-platform.c2
-rw-r--r--drivers/usb/host/ehci-tegra.c23
-rw-r--r--drivers/usb/host/ohci-hub.c18
-rw-r--r--drivers/usb/host/ohci-jz4740.c6
-rw-r--r--drivers/usb/host/ohci-pci.c1
-rw-r--r--drivers/usb/host/ohci.h2
-rw-r--r--drivers/usb/host/xhci-pci.c6
-rw-r--r--drivers/usb/host/xhci-ring.c67
-rw-r--r--drivers/usb/host/xhci.c7
-rw-r--r--drivers/usb/host/xhci.h2
-rw-r--r--drivers/usb/musb/musb_dsps.c5
-rw-r--r--drivers/usb/musb/omap2430.c8
-rw-r--r--drivers/usb/phy/phy-am335x-control.c9
-rw-r--r--drivers/usb/phy/phy-fsm-usb.c9
-rw-r--r--drivers/usb/phy/phy.c3
-rw-r--r--drivers/usb/serial/cp210x.c1
-rw-r--r--drivers/usb/serial/ftdi_sio.c33
-rw-r--r--drivers/usb/serial/ftdi_sio_ids.h37
-rw-r--r--drivers/usb/serial/io_ti.c50
-rw-r--r--drivers/usb/serial/option.c83
-rw-r--r--drivers/usb/serial/pl2303.c3
-rw-r--r--drivers/usb/serial/pl2303.h5
-rw-r--r--drivers/usb/serial/qcserial.c24
-rw-r--r--drivers/usb/serial/sierra.c1
-rw-r--r--drivers/usb/serial/usb-serial.c4
-rw-r--r--drivers/usb/serial/usb_wwan.c9
-rw-r--r--drivers/usb/storage/shuttle_usbat.c2
-rw-r--r--drivers/usb/storage/uas.c13
-rw-r--r--drivers/usb/storage/unusual_devs.h14
-rw-r--r--drivers/usb/usb-common.c2
-rw-r--r--drivers/usb/wusbcore/mmc.c2
-rw-r--r--drivers/usb/wusbcore/wa-xfer.c4
-rw-r--r--drivers/uwb/drp.c14
-rw-r--r--drivers/video/Kconfig2478
-rw-r--r--drivers/video/Makefile166
-rw-r--r--drivers/video/console/sticon.c2
-rw-r--r--drivers/video/console/sticore.c2
-rw-r--r--drivers/video/fbdev/68328fb.c (renamed from drivers/video/68328fb.c)0
-rw-r--r--drivers/video/fbdev/Kconfig2474
-rw-r--r--drivers/video/fbdev/Makefile152
-rw-r--r--drivers/video/fbdev/acornfb.c (renamed from drivers/video/acornfb.c)0
-rw-r--r--drivers/video/fbdev/acornfb.h (renamed from drivers/video/acornfb.h)0
-rw-r--r--drivers/video/fbdev/amba-clcd.c (renamed from drivers/video/amba-clcd.c)0
-rw-r--r--drivers/video/fbdev/amifb.c (renamed from drivers/video/amifb.c)0
-rw-r--r--drivers/video/fbdev/arcfb.c (renamed from drivers/video/arcfb.c)0
-rw-r--r--drivers/video/fbdev/arkfb.c (renamed from drivers/video/arkfb.c)0
-rw-r--r--drivers/video/fbdev/asiliantfb.c (renamed from drivers/video/asiliantfb.c)0
-rw-r--r--drivers/video/fbdev/atafb.c (renamed from drivers/video/atafb.c)49
-rw-r--r--drivers/video/fbdev/atafb.h (renamed from drivers/video/atafb.h)0
-rw-r--r--drivers/video/fbdev/atafb_iplan2p2.c (renamed from drivers/video/atafb_iplan2p2.c)0
-rw-r--r--drivers/video/fbdev/atafb_iplan2p4.c (renamed from drivers/video/atafb_iplan2p4.c)0
-rw-r--r--drivers/video/fbdev/atafb_iplan2p8.c (renamed from drivers/video/atafb_iplan2p8.c)0
-rw-r--r--drivers/video/fbdev/atafb_mfb.c (renamed from drivers/video/atafb_mfb.c)0
-rw-r--r--drivers/video/fbdev/atafb_utils.h (renamed from drivers/video/atafb_utils.h)0
-rw-r--r--drivers/video/fbdev/atmel_lcdfb.c (renamed from drivers/video/atmel_lcdfb.c)0
-rw-r--r--drivers/video/fbdev/aty/Makefile (renamed from drivers/video/aty/Makefile)0
-rw-r--r--drivers/video/fbdev/aty/ati_ids.h (renamed from drivers/video/aty/ati_ids.h)0
-rw-r--r--drivers/video/fbdev/aty/aty128fb.c (renamed from drivers/video/aty/aty128fb.c)0
-rw-r--r--drivers/video/fbdev/aty/atyfb.h (renamed from drivers/video/aty/atyfb.h)0
-rw-r--r--drivers/video/fbdev/aty/atyfb_base.c (renamed from drivers/video/aty/atyfb_base.c)0
-rw-r--r--drivers/video/fbdev/aty/mach64_accel.c (renamed from drivers/video/aty/mach64_accel.c)0
-rw-r--r--drivers/video/fbdev/aty/mach64_ct.c (renamed from drivers/video/aty/mach64_ct.c)0
-rw-r--r--drivers/video/fbdev/aty/mach64_cursor.c (renamed from drivers/video/aty/mach64_cursor.c)2
-rw-r--r--drivers/video/fbdev/aty/mach64_gx.c (renamed from drivers/video/aty/mach64_gx.c)0
-rw-r--r--drivers/video/fbdev/aty/radeon_accel.c (renamed from drivers/video/aty/radeon_accel.c)0
-rw-r--r--drivers/video/fbdev/aty/radeon_backlight.c (renamed from drivers/video/aty/radeon_backlight.c)0
-rw-r--r--drivers/video/fbdev/aty/radeon_base.c (renamed from drivers/video/aty/radeon_base.c)0
-rw-r--r--drivers/video/fbdev/aty/radeon_i2c.c (renamed from drivers/video/aty/radeon_i2c.c)0
-rw-r--r--drivers/video/fbdev/aty/radeon_monitor.c (renamed from drivers/video/aty/radeon_monitor.c)0
-rw-r--r--drivers/video/fbdev/aty/radeon_pm.c (renamed from drivers/video/aty/radeon_pm.c)0
-rw-r--r--drivers/video/fbdev/aty/radeonfb.h (renamed from drivers/video/aty/radeonfb.h)0
-rw-r--r--drivers/video/fbdev/au1100fb.c (renamed from drivers/video/au1100fb.c)0
-rw-r--r--drivers/video/fbdev/au1100fb.h (renamed from drivers/video/au1100fb.h)0
-rw-r--r--drivers/video/fbdev/au1200fb.c (renamed from drivers/video/au1200fb.c)0
-rw-r--r--drivers/video/fbdev/au1200fb.h (renamed from drivers/video/au1200fb.h)0
-rw-r--r--drivers/video/fbdev/auo_k1900fb.c (renamed from drivers/video/auo_k1900fb.c)0
-rw-r--r--drivers/video/fbdev/auo_k1901fb.c (renamed from drivers/video/auo_k1901fb.c)0
-rw-r--r--drivers/video/fbdev/auo_k190x.c (renamed from drivers/video/auo_k190x.c)0
-rw-r--r--drivers/video/fbdev/auo_k190x.h (renamed from drivers/video/auo_k190x.h)0
-rw-r--r--drivers/video/fbdev/bf537-lq035.c (renamed from drivers/video/bf537-lq035.c)0
-rw-r--r--drivers/video/fbdev/bf54x-lq043fb.c (renamed from drivers/video/bf54x-lq043fb.c)2
-rw-r--r--drivers/video/fbdev/bfin-lq035q1-fb.c (renamed from drivers/video/bfin-lq035q1-fb.c)0
-rw-r--r--drivers/video/fbdev/bfin-t350mcqb-fb.c (renamed from drivers/video/bfin-t350mcqb-fb.c)0
-rw-r--r--drivers/video/fbdev/bfin_adv7393fb.c (renamed from drivers/video/bfin_adv7393fb.c)0
-rw-r--r--drivers/video/fbdev/bfin_adv7393fb.h (renamed from drivers/video/bfin_adv7393fb.h)0
-rw-r--r--drivers/video/fbdev/broadsheetfb.c (renamed from drivers/video/broadsheetfb.c)0
-rw-r--r--drivers/video/fbdev/bt431.h (renamed from drivers/video/bt431.h)0
-rw-r--r--drivers/video/fbdev/bt455.h (renamed from drivers/video/bt455.h)0
-rw-r--r--drivers/video/fbdev/bw2.c (renamed from drivers/video/bw2.c)0
-rw-r--r--drivers/video/fbdev/c2p.h (renamed from drivers/video/c2p.h)0
-rw-r--r--drivers/video/fbdev/c2p_core.h (renamed from drivers/video/c2p_core.h)0
-rw-r--r--drivers/video/fbdev/c2p_iplan2.c (renamed from drivers/video/c2p_iplan2.c)0
-rw-r--r--drivers/video/fbdev/c2p_planar.c (renamed from drivers/video/c2p_planar.c)0
-rw-r--r--drivers/video/fbdev/carminefb.c (renamed from drivers/video/carminefb.c)0
-rw-r--r--drivers/video/fbdev/carminefb.h (renamed from drivers/video/carminefb.h)0
-rw-r--r--drivers/video/fbdev/carminefb_regs.h (renamed from drivers/video/carminefb_regs.h)0
-rw-r--r--drivers/video/fbdev/cg14.c (renamed from drivers/video/cg14.c)0
-rw-r--r--drivers/video/fbdev/cg3.c (renamed from drivers/video/cg3.c)0
-rw-r--r--drivers/video/fbdev/cg6.c (renamed from drivers/video/cg6.c)0
-rw-r--r--drivers/video/fbdev/chipsfb.c (renamed from drivers/video/chipsfb.c)0
-rw-r--r--drivers/video/fbdev/cirrusfb.c (renamed from drivers/video/cirrusfb.c)0
-rw-r--r--drivers/video/fbdev/clps711xfb.c (renamed from drivers/video/clps711xfb.c)0
-rw-r--r--drivers/video/fbdev/cobalt_lcdfb.c (renamed from drivers/video/cobalt_lcdfb.c)0
-rw-r--r--drivers/video/fbdev/controlfb.c (renamed from drivers/video/controlfb.c)0
-rw-r--r--drivers/video/fbdev/controlfb.h (renamed from drivers/video/controlfb.h)0
-rw-r--r--drivers/video/fbdev/core/Makefile16
-rw-r--r--drivers/video/fbdev/core/cfbcopyarea.c (renamed from drivers/video/cfbcopyarea.c)0
-rw-r--r--drivers/video/fbdev/core/cfbfillrect.c (renamed from drivers/video/cfbfillrect.c)0
-rw-r--r--drivers/video/fbdev/core/cfbimgblt.c (renamed from drivers/video/cfbimgblt.c)0
-rw-r--r--drivers/video/fbdev/core/fb_ddc.c (renamed from drivers/video/fb_ddc.c)2
-rw-r--r--drivers/video/fbdev/core/fb_defio.c (renamed from drivers/video/fb_defio.c)0
-rw-r--r--drivers/video/fbdev/core/fb_draw.h (renamed from drivers/video/fb_draw.h)0
-rw-r--r--drivers/video/fbdev/core/fb_notify.c (renamed from drivers/video/fb_notify.c)0
-rw-r--r--drivers/video/fbdev/core/fb_sys_fops.c (renamed from drivers/video/fb_sys_fops.c)0
-rw-r--r--drivers/video/fbdev/core/fbcmap.c (renamed from drivers/video/fbcmap.c)0
-rw-r--r--drivers/video/fbdev/core/fbcvt.c (renamed from drivers/video/fbcvt.c)0
-rw-r--r--drivers/video/fbdev/core/fbmem.c (renamed from drivers/video/fbmem.c)0
-rw-r--r--drivers/video/fbdev/core/fbmon.c (renamed from drivers/video/fbmon.c)2
-rw-r--r--drivers/video/fbdev/core/fbsysfs.c (renamed from drivers/video/fbsysfs.c)0
-rw-r--r--drivers/video/fbdev/core/modedb.c (renamed from drivers/video/modedb.c)0
-rw-r--r--drivers/video/fbdev/core/svgalib.c (renamed from drivers/video/svgalib.c)0
-rw-r--r--drivers/video/fbdev/core/syscopyarea.c (renamed from drivers/video/syscopyarea.c)0
-rw-r--r--drivers/video/fbdev/core/sysfillrect.c (renamed from drivers/video/sysfillrect.c)0
-rw-r--r--drivers/video/fbdev/core/sysimgblt.c (renamed from drivers/video/sysimgblt.c)0
-rw-r--r--drivers/video/fbdev/cyber2000fb.c (renamed from drivers/video/cyber2000fb.c)0
-rw-r--r--drivers/video/fbdev/cyber2000fb.h (renamed from drivers/video/cyber2000fb.h)0
-rw-r--r--drivers/video/fbdev/da8xx-fb.c (renamed from drivers/video/da8xx-fb.c)10
-rw-r--r--drivers/video/fbdev/dnfb.c (renamed from drivers/video/dnfb.c)0
-rw-r--r--drivers/video/fbdev/edid.h (renamed from drivers/video/edid.h)0
-rw-r--r--drivers/video/fbdev/efifb.c (renamed from drivers/video/efifb.c)0
-rw-r--r--drivers/video/fbdev/ep93xx-fb.c (renamed from drivers/video/ep93xx-fb.c)0
-rw-r--r--drivers/video/fbdev/exynos/Kconfig (renamed from drivers/video/exynos/Kconfig)0
-rw-r--r--drivers/video/fbdev/exynos/Makefile (renamed from drivers/video/exynos/Makefile)0
-rw-r--r--drivers/video/fbdev/exynos/exynos_mipi_dsi.c (renamed from drivers/video/exynos/exynos_mipi_dsi.c)0
-rw-r--r--drivers/video/fbdev/exynos/exynos_mipi_dsi_common.c (renamed from drivers/video/exynos/exynos_mipi_dsi_common.c)0
-rw-r--r--drivers/video/fbdev/exynos/exynos_mipi_dsi_common.h (renamed from drivers/video/exynos/exynos_mipi_dsi_common.h)0
-rw-r--r--drivers/video/fbdev/exynos/exynos_mipi_dsi_lowlevel.c (renamed from drivers/video/exynos/exynos_mipi_dsi_lowlevel.c)0
-rw-r--r--drivers/video/fbdev/exynos/exynos_mipi_dsi_lowlevel.h (renamed from drivers/video/exynos/exynos_mipi_dsi_lowlevel.h)0
-rw-r--r--drivers/video/fbdev/exynos/exynos_mipi_dsi_regs.h (renamed from drivers/video/exynos/exynos_mipi_dsi_regs.h)0
-rw-r--r--drivers/video/fbdev/exynos/s6e8ax0.c (renamed from drivers/video/exynos/s6e8ax0.c)0
-rw-r--r--drivers/video/fbdev/fb-puv3.c (renamed from drivers/video/fb-puv3.c)0
-rw-r--r--drivers/video/fbdev/ffb.c (renamed from drivers/video/ffb.c)0
-rw-r--r--drivers/video/fbdev/fm2fb.c (renamed from drivers/video/fm2fb.c)0
-rw-r--r--drivers/video/fbdev/fsl-diu-fb.c (renamed from drivers/video/fsl-diu-fb.c)0
-rw-r--r--drivers/video/fbdev/g364fb.c (renamed from drivers/video/g364fb.c)0
-rw-r--r--drivers/video/fbdev/gbefb.c (renamed from drivers/video/gbefb.c)0
-rw-r--r--drivers/video/fbdev/geode/Kconfig (renamed from drivers/video/geode/Kconfig)0
-rw-r--r--drivers/video/fbdev/geode/Makefile (renamed from drivers/video/geode/Makefile)0
-rw-r--r--drivers/video/fbdev/geode/display_gx.c (renamed from drivers/video/geode/display_gx.c)0
-rw-r--r--drivers/video/fbdev/geode/display_gx1.c (renamed from drivers/video/geode/display_gx1.c)0
-rw-r--r--drivers/video/fbdev/geode/display_gx1.h (renamed from drivers/video/geode/display_gx1.h)0
-rw-r--r--drivers/video/fbdev/geode/geodefb.h (renamed from drivers/video/geode/geodefb.h)0
-rw-r--r--drivers/video/fbdev/geode/gx1fb_core.c (renamed from drivers/video/geode/gx1fb_core.c)0
-rw-r--r--drivers/video/fbdev/geode/gxfb.h (renamed from drivers/video/geode/gxfb.h)0
-rw-r--r--drivers/video/fbdev/geode/gxfb_core.c (renamed from drivers/video/geode/gxfb_core.c)0
-rw-r--r--drivers/video/fbdev/geode/lxfb.h (renamed from drivers/video/geode/lxfb.h)0
-rw-r--r--drivers/video/fbdev/geode/lxfb_core.c (renamed from drivers/video/geode/lxfb_core.c)0
-rw-r--r--drivers/video/fbdev/geode/lxfb_ops.c (renamed from drivers/video/geode/lxfb_ops.c)0
-rw-r--r--drivers/video/fbdev/geode/suspend_gx.c (renamed from drivers/video/geode/suspend_gx.c)0
-rw-r--r--drivers/video/fbdev/geode/video_cs5530.c (renamed from drivers/video/geode/video_cs5530.c)0
-rw-r--r--drivers/video/fbdev/geode/video_cs5530.h (renamed from drivers/video/geode/video_cs5530.h)0
-rw-r--r--drivers/video/fbdev/geode/video_gx.c (renamed from drivers/video/geode/video_gx.c)0
-rw-r--r--drivers/video/fbdev/goldfishfb.c (renamed from drivers/video/goldfishfb.c)0
-rw-r--r--drivers/video/fbdev/grvga.c (renamed from drivers/video/grvga.c)0
-rw-r--r--drivers/video/fbdev/gxt4500.c (renamed from drivers/video/gxt4500.c)0
-rw-r--r--drivers/video/fbdev/hecubafb.c (renamed from drivers/video/hecubafb.c)0
-rw-r--r--drivers/video/fbdev/hgafb.c (renamed from drivers/video/hgafb.c)0
-rw-r--r--drivers/video/fbdev/hitfb.c (renamed from drivers/video/hitfb.c)0
-rw-r--r--drivers/video/fbdev/hpfb.c (renamed from drivers/video/hpfb.c)0
-rw-r--r--drivers/video/fbdev/hyperv_fb.c (renamed from drivers/video/hyperv_fb.c)0
-rw-r--r--drivers/video/fbdev/i740_reg.h (renamed from drivers/video/i740_reg.h)0
-rw-r--r--drivers/video/fbdev/i740fb.c (renamed from drivers/video/i740fb.c)0
-rw-r--r--drivers/video/fbdev/i810/Makefile (renamed from drivers/video/i810/Makefile)0
-rw-r--r--drivers/video/fbdev/i810/i810-i2c.c (renamed from drivers/video/i810/i810-i2c.c)0
-rw-r--r--drivers/video/fbdev/i810/i810.h (renamed from drivers/video/i810/i810.h)0
-rw-r--r--drivers/video/fbdev/i810/i810_accel.c (renamed from drivers/video/i810/i810_accel.c)0
-rw-r--r--drivers/video/fbdev/i810/i810_dvt.c (renamed from drivers/video/i810/i810_dvt.c)0
-rw-r--r--drivers/video/fbdev/i810/i810_gtf.c (renamed from drivers/video/i810/i810_gtf.c)0
-rw-r--r--drivers/video/fbdev/i810/i810_main.c (renamed from drivers/video/i810/i810_main.c)0
-rw-r--r--drivers/video/fbdev/i810/i810_main.h (renamed from drivers/video/i810/i810_main.h)0
-rw-r--r--drivers/video/fbdev/i810/i810_regs.h (renamed from drivers/video/i810/i810_regs.h)0
-rw-r--r--drivers/video/fbdev/igafb.c (renamed from drivers/video/igafb.c)0
-rw-r--r--drivers/video/fbdev/imsttfb.c (renamed from drivers/video/imsttfb.c)0
-rw-r--r--drivers/video/fbdev/imxfb.c (renamed from drivers/video/imxfb.c)0
-rw-r--r--drivers/video/fbdev/intelfb/Makefile (renamed from drivers/video/intelfb/Makefile)0
-rw-r--r--drivers/video/fbdev/intelfb/intelfb.h (renamed from drivers/video/intelfb/intelfb.h)0
-rw-r--r--drivers/video/fbdev/intelfb/intelfb_i2c.c (renamed from drivers/video/intelfb/intelfb_i2c.c)0
-rw-r--r--drivers/video/fbdev/intelfb/intelfbdrv.c (renamed from drivers/video/intelfb/intelfbdrv.c)0
-rw-r--r--drivers/video/fbdev/intelfb/intelfbhw.c (renamed from drivers/video/intelfb/intelfbhw.c)0
-rw-r--r--drivers/video/fbdev/intelfb/intelfbhw.h (renamed from drivers/video/intelfb/intelfbhw.h)0
-rw-r--r--drivers/video/fbdev/jz4740_fb.c (renamed from drivers/video/jz4740_fb.c)0
-rw-r--r--drivers/video/fbdev/kyro/Makefile (renamed from drivers/video/kyro/Makefile)0
-rw-r--r--drivers/video/fbdev/kyro/STG4000InitDevice.c (renamed from drivers/video/kyro/STG4000InitDevice.c)0
-rw-r--r--drivers/video/fbdev/kyro/STG4000Interface.h (renamed from drivers/video/kyro/STG4000Interface.h)0
-rw-r--r--drivers/video/fbdev/kyro/STG4000OverlayDevice.c (renamed from drivers/video/kyro/STG4000OverlayDevice.c)0
-rw-r--r--drivers/video/fbdev/kyro/STG4000Ramdac.c (renamed from drivers/video/kyro/STG4000Ramdac.c)0
-rw-r--r--drivers/video/fbdev/kyro/STG4000Reg.h (renamed from drivers/video/kyro/STG4000Reg.h)0
-rw-r--r--drivers/video/fbdev/kyro/STG4000VTG.c (renamed from drivers/video/kyro/STG4000VTG.c)0
-rw-r--r--drivers/video/fbdev/kyro/fbdev.c (renamed from drivers/video/kyro/fbdev.c)0
-rw-r--r--drivers/video/fbdev/leo.c (renamed from drivers/video/leo.c)0
-rw-r--r--drivers/video/fbdev/macfb.c (renamed from drivers/video/macfb.c)0
-rw-r--r--drivers/video/fbdev/macmodes.c (renamed from drivers/video/macmodes.c)0
-rw-r--r--drivers/video/fbdev/macmodes.h (renamed from drivers/video/macmodes.h)0
-rw-r--r--drivers/video/fbdev/matrox/Makefile (renamed from drivers/video/matrox/Makefile)0
-rw-r--r--drivers/video/fbdev/matrox/g450_pll.c (renamed from drivers/video/matrox/g450_pll.c)0
-rw-r--r--drivers/video/fbdev/matrox/g450_pll.h (renamed from drivers/video/matrox/g450_pll.h)0
-rw-r--r--drivers/video/fbdev/matrox/i2c-matroxfb.c (renamed from drivers/video/matrox/i2c-matroxfb.c)0
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_DAC1064.c (renamed from drivers/video/matrox/matroxfb_DAC1064.c)0
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_DAC1064.h (renamed from drivers/video/matrox/matroxfb_DAC1064.h)0
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_Ti3026.c (renamed from drivers/video/matrox/matroxfb_Ti3026.c)0
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_Ti3026.h (renamed from drivers/video/matrox/matroxfb_Ti3026.h)0
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_accel.c (renamed from drivers/video/matrox/matroxfb_accel.c)0
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_accel.h (renamed from drivers/video/matrox/matroxfb_accel.h)0
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_base.c (renamed from drivers/video/matrox/matroxfb_base.c)0
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_base.h (renamed from drivers/video/matrox/matroxfb_base.h)0
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_crtc2.c (renamed from drivers/video/matrox/matroxfb_crtc2.c)0
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_crtc2.h (renamed from drivers/video/matrox/matroxfb_crtc2.h)0
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_g450.c (renamed from drivers/video/matrox/matroxfb_g450.c)0
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_g450.h (renamed from drivers/video/matrox/matroxfb_g450.h)0
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_maven.c (renamed from drivers/video/matrox/matroxfb_maven.c)0
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_maven.h (renamed from drivers/video/matrox/matroxfb_maven.h)0
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_misc.c (renamed from drivers/video/matrox/matroxfb_misc.c)0
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_misc.h (renamed from drivers/video/matrox/matroxfb_misc.h)0
-rw-r--r--drivers/video/fbdev/maxinefb.c (renamed from drivers/video/maxinefb.c)0
-rw-r--r--drivers/video/fbdev/mb862xx/Makefile (renamed from drivers/video/mb862xx/Makefile)0
-rw-r--r--drivers/video/fbdev/mb862xx/mb862xx-i2c.c (renamed from drivers/video/mb862xx/mb862xx-i2c.c)0
-rw-r--r--drivers/video/fbdev/mb862xx/mb862xx_reg.h (renamed from drivers/video/mb862xx/mb862xx_reg.h)0
-rw-r--r--drivers/video/fbdev/mb862xx/mb862xxfb.h (renamed from drivers/video/mb862xx/mb862xxfb.h)0
-rw-r--r--drivers/video/fbdev/mb862xx/mb862xxfb_accel.c (renamed from drivers/video/mb862xx/mb862xxfb_accel.c)0
-rw-r--r--drivers/video/fbdev/mb862xx/mb862xxfb_accel.h (renamed from drivers/video/mb862xx/mb862xxfb_accel.h)0
-rw-r--r--drivers/video/fbdev/mb862xx/mb862xxfbdrv.c (renamed from drivers/video/mb862xx/mb862xxfbdrv.c)0
-rw-r--r--drivers/video/fbdev/mbx/Makefile (renamed from drivers/video/mbx/Makefile)0
-rw-r--r--drivers/video/fbdev/mbx/mbxdebugfs.c (renamed from drivers/video/mbx/mbxdebugfs.c)0
-rw-r--r--drivers/video/fbdev/mbx/mbxfb.c (renamed from drivers/video/mbx/mbxfb.c)0
-rw-r--r--drivers/video/fbdev/mbx/reg_bits.h (renamed from drivers/video/mbx/reg_bits.h)0
-rw-r--r--drivers/video/fbdev/mbx/regs.h (renamed from drivers/video/mbx/regs.h)0
-rw-r--r--drivers/video/fbdev/metronomefb.c (renamed from drivers/video/metronomefb.c)0
-rw-r--r--drivers/video/fbdev/mmp/Kconfig (renamed from drivers/video/mmp/Kconfig)6
-rw-r--r--drivers/video/fbdev/mmp/Makefile (renamed from drivers/video/mmp/Makefile)0
-rw-r--r--drivers/video/fbdev/mmp/core.c (renamed from drivers/video/mmp/core.c)0
-rw-r--r--drivers/video/fbdev/mmp/fb/Kconfig (renamed from drivers/video/mmp/fb/Kconfig)0
-rw-r--r--drivers/video/fbdev/mmp/fb/Makefile (renamed from drivers/video/mmp/fb/Makefile)0
-rw-r--r--drivers/video/fbdev/mmp/fb/mmpfb.c (renamed from drivers/video/mmp/fb/mmpfb.c)0
-rw-r--r--drivers/video/fbdev/mmp/fb/mmpfb.h (renamed from drivers/video/mmp/fb/mmpfb.h)0
-rw-r--r--drivers/video/fbdev/mmp/hw/Kconfig (renamed from drivers/video/mmp/hw/Kconfig)0
-rw-r--r--drivers/video/fbdev/mmp/hw/Makefile (renamed from drivers/video/mmp/hw/Makefile)0
-rw-r--r--drivers/video/fbdev/mmp/hw/mmp_ctrl.c (renamed from drivers/video/mmp/hw/mmp_ctrl.c)0
-rw-r--r--drivers/video/fbdev/mmp/hw/mmp_ctrl.h (renamed from drivers/video/mmp/hw/mmp_ctrl.h)0
-rw-r--r--drivers/video/fbdev/mmp/hw/mmp_spi.c (renamed from drivers/video/mmp/hw/mmp_spi.c)0
-rw-r--r--drivers/video/fbdev/mmp/panel/Kconfig (renamed from drivers/video/mmp/panel/Kconfig)0
-rw-r--r--drivers/video/fbdev/mmp/panel/Makefile (renamed from drivers/video/mmp/panel/Makefile)0
-rw-r--r--drivers/video/fbdev/mmp/panel/tpo_tj032md01bw.c (renamed from drivers/video/mmp/panel/tpo_tj032md01bw.c)0
-rw-r--r--drivers/video/fbdev/msm/Makefile (renamed from drivers/video/msm/Makefile)0
-rw-r--r--drivers/video/fbdev/msm/mddi.c (renamed from drivers/video/msm/mddi.c)0
-rw-r--r--drivers/video/fbdev/msm/mddi_client_dummy.c (renamed from drivers/video/msm/mddi_client_dummy.c)0
-rw-r--r--drivers/video/fbdev/msm/mddi_client_nt35399.c (renamed from drivers/video/msm/mddi_client_nt35399.c)0
-rw-r--r--drivers/video/fbdev/msm/mddi_client_toshiba.c (renamed from drivers/video/msm/mddi_client_toshiba.c)0
-rw-r--r--drivers/video/fbdev/msm/mddi_hw.h (renamed from drivers/video/msm/mddi_hw.h)0
-rw-r--r--drivers/video/fbdev/msm/mdp.c (renamed from drivers/video/msm/mdp.c)0
-rw-r--r--drivers/video/fbdev/msm/mdp_csc_table.h (renamed from drivers/video/msm/mdp_csc_table.h)0
-rw-r--r--drivers/video/fbdev/msm/mdp_hw.h (renamed from drivers/video/msm/mdp_hw.h)0
-rw-r--r--drivers/video/fbdev/msm/mdp_ppp.c (renamed from drivers/video/msm/mdp_ppp.c)0
-rw-r--r--drivers/video/fbdev/msm/mdp_scale_tables.c (renamed from drivers/video/msm/mdp_scale_tables.c)0
-rw-r--r--drivers/video/fbdev/msm/mdp_scale_tables.h (renamed from drivers/video/msm/mdp_scale_tables.h)0
-rw-r--r--drivers/video/fbdev/msm/msm_fb.c (renamed from drivers/video/msm/msm_fb.c)0
-rw-r--r--drivers/video/fbdev/mx3fb.c (renamed from drivers/video/mx3fb.c)0
-rw-r--r--drivers/video/fbdev/mxsfb.c (renamed from drivers/video/mxsfb.c)0
-rw-r--r--drivers/video/fbdev/n411.c (renamed from drivers/video/n411.c)0
-rw-r--r--drivers/video/fbdev/neofb.c (renamed from drivers/video/neofb.c)0
-rw-r--r--drivers/video/fbdev/nuc900fb.c (renamed from drivers/video/nuc900fb.c)0
-rw-r--r--drivers/video/fbdev/nuc900fb.h (renamed from drivers/video/nuc900fb.h)0
-rw-r--r--drivers/video/fbdev/nvidia/Makefile (renamed from drivers/video/nvidia/Makefile)0
-rw-r--r--drivers/video/fbdev/nvidia/nv_accel.c (renamed from drivers/video/nvidia/nv_accel.c)0
-rw-r--r--drivers/video/fbdev/nvidia/nv_backlight.c (renamed from drivers/video/nvidia/nv_backlight.c)0
-rw-r--r--drivers/video/fbdev/nvidia/nv_dma.h (renamed from drivers/video/nvidia/nv_dma.h)0
-rw-r--r--drivers/video/fbdev/nvidia/nv_hw.c (renamed from drivers/video/nvidia/nv_hw.c)0
-rw-r--r--drivers/video/fbdev/nvidia/nv_i2c.c (renamed from drivers/video/nvidia/nv_i2c.c)0
-rw-r--r--drivers/video/fbdev/nvidia/nv_local.h (renamed from drivers/video/nvidia/nv_local.h)0
-rw-r--r--drivers/video/fbdev/nvidia/nv_of.c (renamed from drivers/video/nvidia/nv_of.c)0
-rw-r--r--drivers/video/fbdev/nvidia/nv_proto.h (renamed from drivers/video/nvidia/nv_proto.h)0
-rw-r--r--drivers/video/fbdev/nvidia/nv_setup.c (renamed from drivers/video/nvidia/nv_setup.c)0
-rw-r--r--drivers/video/fbdev/nvidia/nv_type.h (renamed from drivers/video/nvidia/nv_type.h)0
-rw-r--r--drivers/video/fbdev/nvidia/nvidia.c (renamed from drivers/video/nvidia/nvidia.c)0
-rw-r--r--drivers/video/fbdev/ocfb.c (renamed from drivers/video/ocfb.c)0
-rw-r--r--drivers/video/fbdev/offb.c (renamed from drivers/video/offb.c)0
-rw-r--r--drivers/video/fbdev/omap/Kconfig (renamed from drivers/video/omap/Kconfig)0
-rw-r--r--drivers/video/fbdev/omap/Makefile (renamed from drivers/video/omap/Makefile)0
-rw-r--r--drivers/video/fbdev/omap/hwa742.c (renamed from drivers/video/omap/hwa742.c)0
-rw-r--r--drivers/video/fbdev/omap/lcd_ams_delta.c (renamed from drivers/video/omap/lcd_ams_delta.c)0
-rw-r--r--drivers/video/fbdev/omap/lcd_h3.c (renamed from drivers/video/omap/lcd_h3.c)0
-rw-r--r--drivers/video/fbdev/omap/lcd_htcherald.c (renamed from drivers/video/omap/lcd_htcherald.c)0
-rw-r--r--drivers/video/fbdev/omap/lcd_inn1510.c (renamed from drivers/video/omap/lcd_inn1510.c)0
-rw-r--r--drivers/video/fbdev/omap/lcd_inn1610.c (renamed from drivers/video/omap/lcd_inn1610.c)0
-rw-r--r--drivers/video/fbdev/omap/lcd_mipid.c (renamed from drivers/video/omap/lcd_mipid.c)0
-rw-r--r--drivers/video/fbdev/omap/lcd_osk.c (renamed from drivers/video/omap/lcd_osk.c)0
-rw-r--r--drivers/video/fbdev/omap/lcd_palmte.c (renamed from drivers/video/omap/lcd_palmte.c)0
-rw-r--r--drivers/video/fbdev/omap/lcd_palmtt.c (renamed from drivers/video/omap/lcd_palmtt.c)0
-rw-r--r--drivers/video/fbdev/omap/lcd_palmz71.c (renamed from drivers/video/omap/lcd_palmz71.c)0
-rw-r--r--drivers/video/fbdev/omap/lcdc.c (renamed from drivers/video/omap/lcdc.c)0
-rw-r--r--drivers/video/fbdev/omap/lcdc.h (renamed from drivers/video/omap/lcdc.h)0
-rw-r--r--drivers/video/fbdev/omap/omapfb.h (renamed from drivers/video/omap/omapfb.h)0
-rw-r--r--drivers/video/fbdev/omap/omapfb_main.c (renamed from drivers/video/omap/omapfb_main.c)0
-rw-r--r--drivers/video/fbdev/omap/sossi.c (renamed from drivers/video/omap/sossi.c)0
-rw-r--r--drivers/video/fbdev/omap2/Kconfig10
-rw-r--r--drivers/video/fbdev/omap2/Makefile (renamed from drivers/video/omap2/Makefile)0
-rw-r--r--drivers/video/fbdev/omap2/displays-new/Kconfig (renamed from drivers/video/omap2/displays-new/Kconfig)0
-rw-r--r--drivers/video/fbdev/omap2/displays-new/Makefile (renamed from drivers/video/omap2/displays-new/Makefile)0
-rw-r--r--drivers/video/fbdev/omap2/displays-new/connector-analog-tv.c (renamed from drivers/video/omap2/displays-new/connector-analog-tv.c)0
-rw-r--r--drivers/video/fbdev/omap2/displays-new/connector-dvi.c (renamed from drivers/video/omap2/displays-new/connector-dvi.c)0
-rw-r--r--drivers/video/fbdev/omap2/displays-new/connector-hdmi.c (renamed from drivers/video/omap2/displays-new/connector-hdmi.c)0
-rw-r--r--drivers/video/fbdev/omap2/displays-new/encoder-tfp410.c (renamed from drivers/video/omap2/displays-new/encoder-tfp410.c)0
-rw-r--r--drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c (renamed from drivers/video/omap2/displays-new/encoder-tpd12s015.c)0
-rw-r--r--drivers/video/fbdev/omap2/displays-new/panel-dpi.c (renamed from drivers/video/omap2/displays-new/panel-dpi.c)0
-rw-r--r--drivers/video/fbdev/omap2/displays-new/panel-dsi-cm.c (renamed from drivers/video/omap2/displays-new/panel-dsi-cm.c)0
-rw-r--r--drivers/video/fbdev/omap2/displays-new/panel-lgphilips-lb035q02.c (renamed from drivers/video/omap2/displays-new/panel-lgphilips-lb035q02.c)0
-rw-r--r--drivers/video/fbdev/omap2/displays-new/panel-nec-nl8048hl11.c (renamed from drivers/video/omap2/displays-new/panel-nec-nl8048hl11.c)0
-rw-r--r--drivers/video/fbdev/omap2/displays-new/panel-sharp-ls037v7dw01.c (renamed from drivers/video/omap2/displays-new/panel-sharp-ls037v7dw01.c)0
-rw-r--r--drivers/video/fbdev/omap2/displays-new/panel-sony-acx565akm.c (renamed from drivers/video/omap2/displays-new/panel-sony-acx565akm.c)0
-rw-r--r--drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c (renamed from drivers/video/omap2/displays-new/panel-tpo-td028ttec1.c)0
-rw-r--r--drivers/video/fbdev/omap2/displays-new/panel-tpo-td043mtea1.c (renamed from drivers/video/omap2/displays-new/panel-tpo-td043mtea1.c)0
-rw-r--r--drivers/video/fbdev/omap2/dss/Kconfig (renamed from drivers/video/omap2/dss/Kconfig)0
-rw-r--r--drivers/video/fbdev/omap2/dss/Makefile (renamed from drivers/video/omap2/dss/Makefile)0
-rw-r--r--drivers/video/fbdev/omap2/dss/apply.c (renamed from drivers/video/omap2/dss/apply.c)0
-rw-r--r--drivers/video/fbdev/omap2/dss/core.c (renamed from drivers/video/omap2/dss/core.c)0
-rw-r--r--drivers/video/fbdev/omap2/dss/dispc-compat.c (renamed from drivers/video/omap2/dss/dispc-compat.c)0
-rw-r--r--drivers/video/fbdev/omap2/dss/dispc-compat.h (renamed from drivers/video/omap2/dss/dispc-compat.h)0
-rw-r--r--drivers/video/fbdev/omap2/dss/dispc.c (renamed from drivers/video/omap2/dss/dispc.c)67
-rw-r--r--drivers/video/fbdev/omap2/dss/dispc.h (renamed from drivers/video/omap2/dss/dispc.h)0
-rw-r--r--drivers/video/fbdev/omap2/dss/dispc_coefs.c (renamed from drivers/video/omap2/dss/dispc_coefs.c)0
-rw-r--r--drivers/video/fbdev/omap2/dss/display-sysfs.c (renamed from drivers/video/omap2/dss/display-sysfs.c)0
-rw-r--r--drivers/video/fbdev/omap2/dss/display.c (renamed from drivers/video/omap2/dss/display.c)0
-rw-r--r--drivers/video/fbdev/omap2/dss/dpi.c (renamed from drivers/video/omap2/dss/dpi.c)0
-rw-r--r--drivers/video/fbdev/omap2/dss/dsi.c (renamed from drivers/video/omap2/dss/dsi.c)20
-rw-r--r--drivers/video/fbdev/omap2/dss/dss-of.c (renamed from drivers/video/omap2/dss/dss-of.c)0
-rw-r--r--drivers/video/fbdev/omap2/dss/dss.c (renamed from drivers/video/omap2/dss/dss.c)4
-rw-r--r--drivers/video/fbdev/omap2/dss/dss.h (renamed from drivers/video/omap2/dss/dss.h)6
-rw-r--r--drivers/video/fbdev/omap2/dss/dss_features.c (renamed from drivers/video/omap2/dss/dss_features.c)0
-rw-r--r--drivers/video/fbdev/omap2/dss/dss_features.h (renamed from drivers/video/omap2/dss/dss_features.h)0
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi.h (renamed from drivers/video/omap2/dss/hdmi.h)0
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi4.c (renamed from drivers/video/omap2/dss/hdmi4.c)0
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi4_core.c (renamed from drivers/video/omap2/dss/hdmi4_core.c)0
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi4_core.h (renamed from drivers/video/omap2/dss/hdmi4_core.h)0
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi_common.c (renamed from drivers/video/omap2/dss/hdmi_common.c)8
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi_phy.c (renamed from drivers/video/omap2/dss/hdmi_phy.c)0
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi_pll.c (renamed from drivers/video/omap2/dss/hdmi_pll.c)0
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi_wp.c (renamed from drivers/video/omap2/dss/hdmi_wp.c)0
-rw-r--r--drivers/video/fbdev/omap2/dss/manager-sysfs.c (renamed from drivers/video/omap2/dss/manager-sysfs.c)0
-rw-r--r--drivers/video/fbdev/omap2/dss/manager.c (renamed from drivers/video/omap2/dss/manager.c)0
-rw-r--r--drivers/video/fbdev/omap2/dss/output.c (renamed from drivers/video/omap2/dss/output.c)0
-rw-r--r--drivers/video/fbdev/omap2/dss/overlay-sysfs.c (renamed from drivers/video/omap2/dss/overlay-sysfs.c)0
-rw-r--r--drivers/video/fbdev/omap2/dss/overlay.c (renamed from drivers/video/omap2/dss/overlay.c)0
-rw-r--r--drivers/video/fbdev/omap2/dss/rfbi.c (renamed from drivers/video/omap2/dss/rfbi.c)0
-rw-r--r--drivers/video/fbdev/omap2/dss/sdi.c (renamed from drivers/video/omap2/dss/sdi.c)0
-rw-r--r--drivers/video/fbdev/omap2/dss/venc.c (renamed from drivers/video/omap2/dss/venc.c)0
-rw-r--r--drivers/video/fbdev/omap2/dss/venc_panel.c (renamed from drivers/video/omap2/dss/venc_panel.c)0
-rw-r--r--drivers/video/fbdev/omap2/omapfb/Kconfig (renamed from drivers/video/omap2/omapfb/Kconfig)0
-rw-r--r--drivers/video/fbdev/omap2/omapfb/Makefile (renamed from drivers/video/omap2/omapfb/Makefile)0
-rw-r--r--drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c (renamed from drivers/video/omap2/omapfb/omapfb-ioctl.c)0
-rw-r--r--drivers/video/fbdev/omap2/omapfb/omapfb-main.c (renamed from drivers/video/omap2/omapfb/omapfb-main.c)0
-rw-r--r--drivers/video/fbdev/omap2/omapfb/omapfb-sysfs.c (renamed from drivers/video/omap2/omapfb/omapfb-sysfs.c)0
-rw-r--r--drivers/video/fbdev/omap2/omapfb/omapfb.h (renamed from drivers/video/omap2/omapfb/omapfb.h)0
-rw-r--r--drivers/video/fbdev/omap2/vrfb.c (renamed from drivers/video/omap2/vrfb.c)0
-rw-r--r--drivers/video/fbdev/p9100.c (renamed from drivers/video/p9100.c)0
-rw-r--r--drivers/video/fbdev/platinumfb.c (renamed from drivers/video/platinumfb.c)0
-rw-r--r--drivers/video/fbdev/platinumfb.h (renamed from drivers/video/platinumfb.h)0
-rw-r--r--drivers/video/fbdev/pm2fb.c (renamed from drivers/video/pm2fb.c)0
-rw-r--r--drivers/video/fbdev/pm3fb.c (renamed from drivers/video/pm3fb.c)0
-rw-r--r--drivers/video/fbdev/pmag-aa-fb.c (renamed from drivers/video/pmag-aa-fb.c)0
-rw-r--r--drivers/video/fbdev/pmag-ba-fb.c (renamed from drivers/video/pmag-ba-fb.c)0
-rw-r--r--drivers/video/fbdev/pmagb-b-fb.c (renamed from drivers/video/pmagb-b-fb.c)0
-rw-r--r--drivers/video/fbdev/ps3fb.c (renamed from drivers/video/ps3fb.c)0
-rw-r--r--drivers/video/fbdev/pvr2fb.c (renamed from drivers/video/pvr2fb.c)0
-rw-r--r--drivers/video/fbdev/pxa168fb.c (renamed from drivers/video/pxa168fb.c)0
-rw-r--r--drivers/video/fbdev/pxa168fb.h (renamed from drivers/video/pxa168fb.h)0
-rw-r--r--drivers/video/fbdev/pxa3xx-gcu.c (renamed from drivers/video/pxa3xx-gcu.c)0
-rw-r--r--drivers/video/fbdev/pxa3xx-gcu.h (renamed from drivers/video/pxa3xx-gcu.h)0
-rw-r--r--drivers/video/fbdev/pxafb.c (renamed from drivers/video/pxafb.c)0
-rw-r--r--drivers/video/fbdev/pxafb.h (renamed from drivers/video/pxafb.h)0
-rw-r--r--drivers/video/fbdev/q40fb.c (renamed from drivers/video/q40fb.c)0
-rw-r--r--drivers/video/fbdev/riva/Makefile (renamed from drivers/video/riva/Makefile)0
-rw-r--r--drivers/video/fbdev/riva/fbdev.c (renamed from drivers/video/riva/fbdev.c)0
-rw-r--r--drivers/video/fbdev/riva/nv_driver.c (renamed from drivers/video/riva/nv_driver.c)0
-rw-r--r--drivers/video/fbdev/riva/nv_type.h (renamed from drivers/video/riva/nv_type.h)0
-rw-r--r--drivers/video/fbdev/riva/nvreg.h (renamed from drivers/video/riva/nvreg.h)0
-rw-r--r--drivers/video/fbdev/riva/riva_hw.c (renamed from drivers/video/riva/riva_hw.c)0
-rw-r--r--drivers/video/fbdev/riva/riva_hw.h (renamed from drivers/video/riva/riva_hw.h)0
-rw-r--r--drivers/video/fbdev/riva/riva_tbl.h (renamed from drivers/video/riva/riva_tbl.h)0
-rw-r--r--drivers/video/fbdev/riva/rivafb-i2c.c (renamed from drivers/video/riva/rivafb-i2c.c)0
-rw-r--r--drivers/video/fbdev/riva/rivafb.h (renamed from drivers/video/riva/rivafb.h)0
-rw-r--r--drivers/video/fbdev/s1d13xxxfb.c (renamed from drivers/video/s1d13xxxfb.c)0
-rw-r--r--drivers/video/fbdev/s3c-fb.c (renamed from drivers/video/s3c-fb.c)0
-rw-r--r--drivers/video/fbdev/s3c2410fb.c (renamed from drivers/video/s3c2410fb.c)0
-rw-r--r--drivers/video/fbdev/s3c2410fb.h (renamed from drivers/video/s3c2410fb.h)0
-rw-r--r--drivers/video/fbdev/s3fb.c (renamed from drivers/video/s3fb.c)0
-rw-r--r--drivers/video/fbdev/sa1100fb.c (renamed from drivers/video/sa1100fb.c)0
-rw-r--r--drivers/video/fbdev/sa1100fb.h (renamed from drivers/video/sa1100fb.h)0
-rw-r--r--drivers/video/fbdev/savage/Makefile (renamed from drivers/video/savage/Makefile)0
-rw-r--r--drivers/video/fbdev/savage/savagefb-i2c.c (renamed from drivers/video/savage/savagefb-i2c.c)0
-rw-r--r--drivers/video/fbdev/savage/savagefb.h (renamed from drivers/video/savage/savagefb.h)0
-rw-r--r--drivers/video/fbdev/savage/savagefb_accel.c (renamed from drivers/video/savage/savagefb_accel.c)0
-rw-r--r--drivers/video/fbdev/savage/savagefb_driver.c (renamed from drivers/video/savage/savagefb_driver.c)0
-rw-r--r--drivers/video/fbdev/sbuslib.c (renamed from drivers/video/sbuslib.c)0
-rw-r--r--drivers/video/fbdev/sbuslib.h (renamed from drivers/video/sbuslib.h)0
-rw-r--r--drivers/video/fbdev/sh7760fb.c (renamed from drivers/video/sh7760fb.c)0
-rw-r--r--drivers/video/fbdev/sh_mipi_dsi.c (renamed from drivers/video/sh_mipi_dsi.c)0
-rw-r--r--drivers/video/fbdev/sh_mobile_hdmi.c (renamed from drivers/video/sh_mobile_hdmi.c)0
-rw-r--r--drivers/video/fbdev/sh_mobile_lcdcfb.c (renamed from drivers/video/sh_mobile_lcdcfb.c)0
-rw-r--r--drivers/video/fbdev/sh_mobile_lcdcfb.h (renamed from drivers/video/sh_mobile_lcdcfb.h)0
-rw-r--r--drivers/video/fbdev/sh_mobile_meram.c (renamed from drivers/video/sh_mobile_meram.c)0
-rw-r--r--drivers/video/fbdev/simplefb.c (renamed from drivers/video/simplefb.c)0
-rw-r--r--drivers/video/fbdev/sis/300vtbl.h (renamed from drivers/video/sis/300vtbl.h)0
-rw-r--r--drivers/video/fbdev/sis/310vtbl.h (renamed from drivers/video/sis/310vtbl.h)0
-rw-r--r--drivers/video/fbdev/sis/Makefile (renamed from drivers/video/sis/Makefile)0
-rw-r--r--drivers/video/fbdev/sis/init.c (renamed from drivers/video/sis/init.c)0
-rw-r--r--drivers/video/fbdev/sis/init.h (renamed from drivers/video/sis/init.h)0
-rw-r--r--drivers/video/fbdev/sis/init301.c (renamed from drivers/video/sis/init301.c)0
-rw-r--r--drivers/video/fbdev/sis/init301.h (renamed from drivers/video/sis/init301.h)0
-rw-r--r--drivers/video/fbdev/sis/initdef.h (renamed from drivers/video/sis/initdef.h)0
-rw-r--r--drivers/video/fbdev/sis/initextlfb.c (renamed from drivers/video/sis/initextlfb.c)0
-rw-r--r--drivers/video/fbdev/sis/oem300.h (renamed from drivers/video/sis/oem300.h)0
-rw-r--r--drivers/video/fbdev/sis/oem310.h (renamed from drivers/video/sis/oem310.h)0
-rw-r--r--drivers/video/fbdev/sis/sis.h (renamed from drivers/video/sis/sis.h)0
-rw-r--r--drivers/video/fbdev/sis/sis_accel.c (renamed from drivers/video/sis/sis_accel.c)0
-rw-r--r--drivers/video/fbdev/sis/sis_accel.h (renamed from drivers/video/sis/sis_accel.h)0
-rw-r--r--drivers/video/fbdev/sis/sis_main.c (renamed from drivers/video/sis/sis_main.c)0
-rw-r--r--drivers/video/fbdev/sis/sis_main.h (renamed from drivers/video/sis/sis_main.h)0
-rw-r--r--drivers/video/fbdev/sis/vgatypes.h (renamed from drivers/video/sis/vgatypes.h)0
-rw-r--r--drivers/video/fbdev/sis/vstruct.h (renamed from drivers/video/sis/vstruct.h)0
-rw-r--r--drivers/video/fbdev/skeletonfb.c (renamed from drivers/video/skeletonfb.c)0
-rw-r--r--drivers/video/fbdev/sm501fb.c (renamed from drivers/video/sm501fb.c)0
-rw-r--r--drivers/video/fbdev/smscufx.c (renamed from drivers/video/smscufx.c)0
-rw-r--r--drivers/video/fbdev/ssd1307fb.c (renamed from drivers/video/ssd1307fb.c)0
-rw-r--r--drivers/video/fbdev/sstfb.c (renamed from drivers/video/sstfb.c)0
-rw-r--r--drivers/video/fbdev/sticore.h (renamed from drivers/video/sticore.h)0
-rw-r--r--drivers/video/fbdev/stifb.c (renamed from drivers/video/stifb.c)0
-rw-r--r--drivers/video/fbdev/sunxvr1000.c (renamed from drivers/video/sunxvr1000.c)0
-rw-r--r--drivers/video/fbdev/sunxvr2500.c (renamed from drivers/video/sunxvr2500.c)0
-rw-r--r--drivers/video/fbdev/sunxvr500.c (renamed from drivers/video/sunxvr500.c)0
-rw-r--r--drivers/video/fbdev/tcx.c (renamed from drivers/video/tcx.c)0
-rw-r--r--drivers/video/fbdev/tdfxfb.c (renamed from drivers/video/tdfxfb.c)0
-rw-r--r--drivers/video/fbdev/tgafb.c (renamed from drivers/video/tgafb.c)0
-rw-r--r--drivers/video/fbdev/tmiofb.c (renamed from drivers/video/tmiofb.c)0
-rw-r--r--drivers/video/fbdev/tridentfb.c (renamed from drivers/video/tridentfb.c)0
-rw-r--r--drivers/video/fbdev/udlfb.c (renamed from drivers/video/udlfb.c)0
-rw-r--r--drivers/video/fbdev/uvesafb.c (renamed from drivers/video/uvesafb.c)0
-rw-r--r--drivers/video/fbdev/valkyriefb.c (renamed from drivers/video/valkyriefb.c)0
-rw-r--r--drivers/video/fbdev/valkyriefb.h (renamed from drivers/video/valkyriefb.h)0
-rw-r--r--drivers/video/fbdev/vermilion/Makefile (renamed from drivers/video/vermilion/Makefile)0
-rw-r--r--drivers/video/fbdev/vermilion/cr_pll.c (renamed from drivers/video/vermilion/cr_pll.c)0
-rw-r--r--drivers/video/fbdev/vermilion/vermilion.c (renamed from drivers/video/vermilion/vermilion.c)0
-rw-r--r--drivers/video/fbdev/vermilion/vermilion.h (renamed from drivers/video/vermilion/vermilion.h)0
-rw-r--r--drivers/video/fbdev/vesafb.c (renamed from drivers/video/vesafb.c)0
-rw-r--r--drivers/video/fbdev/vfb.c (renamed from drivers/video/vfb.c)0
-rw-r--r--drivers/video/fbdev/vga16fb.c (renamed from drivers/video/vga16fb.c)0
-rw-r--r--drivers/video/fbdev/via/Makefile (renamed from drivers/video/via/Makefile)0
-rw-r--r--drivers/video/fbdev/via/accel.c (renamed from drivers/video/via/accel.c)0
-rw-r--r--drivers/video/fbdev/via/accel.h (renamed from drivers/video/via/accel.h)0
-rw-r--r--drivers/video/fbdev/via/chip.h (renamed from drivers/video/via/chip.h)0
-rw-r--r--drivers/video/fbdev/via/debug.h (renamed from drivers/video/via/debug.h)0
-rw-r--r--drivers/video/fbdev/via/dvi.c (renamed from drivers/video/via/dvi.c)0
-rw-r--r--drivers/video/fbdev/via/dvi.h (renamed from drivers/video/via/dvi.h)0
-rw-r--r--drivers/video/fbdev/via/global.c (renamed from drivers/video/via/global.c)0
-rw-r--r--drivers/video/fbdev/via/global.h (renamed from drivers/video/via/global.h)0
-rw-r--r--drivers/video/fbdev/via/hw.c (renamed from drivers/video/via/hw.c)0
-rw-r--r--drivers/video/fbdev/via/hw.h (renamed from drivers/video/via/hw.h)0
-rw-r--r--drivers/video/fbdev/via/ioctl.c (renamed from drivers/video/via/ioctl.c)0
-rw-r--r--drivers/video/fbdev/via/ioctl.h (renamed from drivers/video/via/ioctl.h)0
-rw-r--r--drivers/video/fbdev/via/lcd.c (renamed from drivers/video/via/lcd.c)0
-rw-r--r--drivers/video/fbdev/via/lcd.h (renamed from drivers/video/via/lcd.h)0
-rw-r--r--drivers/video/fbdev/via/share.h (renamed from drivers/video/via/share.h)0
-rw-r--r--drivers/video/fbdev/via/tblDPASetting.c (renamed from drivers/video/via/tblDPASetting.c)0
-rw-r--r--drivers/video/fbdev/via/tblDPASetting.h (renamed from drivers/video/via/tblDPASetting.h)0
-rw-r--r--drivers/video/fbdev/via/via-core.c (renamed from drivers/video/via/via-core.c)0
-rw-r--r--drivers/video/fbdev/via/via-gpio.c (renamed from drivers/video/via/via-gpio.c)0
-rw-r--r--drivers/video/fbdev/via/via_aux.c (renamed from drivers/video/via/via_aux.c)0
-rw-r--r--drivers/video/fbdev/via/via_aux.h (renamed from drivers/video/via/via_aux.h)0
-rw-r--r--drivers/video/fbdev/via/via_aux_ch7301.c (renamed from drivers/video/via/via_aux_ch7301.c)0
-rw-r--r--drivers/video/fbdev/via/via_aux_edid.c (renamed from drivers/video/via/via_aux_edid.c)0
-rw-r--r--drivers/video/fbdev/via/via_aux_sii164.c (renamed from drivers/video/via/via_aux_sii164.c)0
-rw-r--r--drivers/video/fbdev/via/via_aux_vt1621.c (renamed from drivers/video/via/via_aux_vt1621.c)0
-rw-r--r--drivers/video/fbdev/via/via_aux_vt1622.c (renamed from drivers/video/via/via_aux_vt1622.c)0
-rw-r--r--drivers/video/fbdev/via/via_aux_vt1625.c (renamed from drivers/video/via/via_aux_vt1625.c)0
-rw-r--r--drivers/video/fbdev/via/via_aux_vt1631.c (renamed from drivers/video/via/via_aux_vt1631.c)0
-rw-r--r--drivers/video/fbdev/via/via_aux_vt1632.c (renamed from drivers/video/via/via_aux_vt1632.c)0
-rw-r--r--drivers/video/fbdev/via/via_aux_vt1636.c (renamed from drivers/video/via/via_aux_vt1636.c)0
-rw-r--r--drivers/video/fbdev/via/via_clock.c (renamed from drivers/video/via/via_clock.c)0
-rw-r--r--drivers/video/fbdev/via/via_clock.h (renamed from drivers/video/via/via_clock.h)0
-rw-r--r--drivers/video/fbdev/via/via_i2c.c (renamed from drivers/video/via/via_i2c.c)0
-rw-r--r--drivers/video/fbdev/via/via_modesetting.c (renamed from drivers/video/via/via_modesetting.c)0
-rw-r--r--drivers/video/fbdev/via/via_modesetting.h (renamed from drivers/video/via/via_modesetting.h)0
-rw-r--r--drivers/video/fbdev/via/via_utility.c (renamed from drivers/video/via/via_utility.c)0
-rw-r--r--drivers/video/fbdev/via/via_utility.h (renamed from drivers/video/via/via_utility.h)0
-rw-r--r--drivers/video/fbdev/via/viafbdev.c (renamed from drivers/video/via/viafbdev.c)0
-rw-r--r--drivers/video/fbdev/via/viafbdev.h (renamed from drivers/video/via/viafbdev.h)0
-rw-r--r--drivers/video/fbdev/via/viamode.c (renamed from drivers/video/via/viamode.c)0
-rw-r--r--drivers/video/fbdev/via/viamode.h (renamed from drivers/video/via/viamode.h)0
-rw-r--r--drivers/video/fbdev/via/vt1636.c (renamed from drivers/video/via/vt1636.c)0
-rw-r--r--drivers/video/fbdev/via/vt1636.h (renamed from drivers/video/via/vt1636.h)0
-rw-r--r--drivers/video/fbdev/vt8500lcdfb.c (renamed from drivers/video/vt8500lcdfb.c)0
-rw-r--r--drivers/video/fbdev/vt8500lcdfb.h (renamed from drivers/video/vt8500lcdfb.h)0
-rw-r--r--drivers/video/fbdev/vt8623fb.c (renamed from drivers/video/vt8623fb.c)0
-rw-r--r--drivers/video/fbdev/w100fb.c (renamed from drivers/video/w100fb.c)0
-rw-r--r--drivers/video/fbdev/w100fb.h (renamed from drivers/video/w100fb.h)0
-rw-r--r--drivers/video/fbdev/wm8505fb.c (renamed from drivers/video/wm8505fb.c)0
-rw-r--r--drivers/video/fbdev/wm8505fb_regs.h (renamed from drivers/video/wm8505fb_regs.h)0
-rw-r--r--drivers/video/fbdev/wmt_ge_rops.c (renamed from drivers/video/wmt_ge_rops.c)2
-rw-r--r--drivers/video/fbdev/wmt_ge_rops.h (renamed from drivers/video/wmt_ge_rops.h)0
-rw-r--r--drivers/video/fbdev/xen-fbfront.c (renamed from drivers/video/xen-fbfront.c)0
-rw-r--r--drivers/video/fbdev/xilinxfb.c (renamed from drivers/video/xilinxfb.c)0
-rw-r--r--drivers/video/omap2/Kconfig10
-rw-r--r--drivers/vme/bridges/vme_tsi148.c22
-rw-r--r--drivers/w1/w1.c32
-rw-r--r--drivers/w1/w1_netlink.c44
-rw-r--r--drivers/xen/events/events_fifo.c41
-rw-r--r--drivers/xen/manage.c77
-rw-r--r--drivers/xen/xen-acpi-processor.c4
-rw-r--r--drivers/xen/xen-pciback/pci_stub.c25
-rw-r--r--drivers/xen/xen-pciback/pciback_ops.c3
-rw-r--r--drivers/xen/xen-pciback/vpci.c2
-rw-r--r--drivers/xen/xen-pciback/xenbus.c4
-rw-r--r--drivers/xen/xenbus/xenbus_xs.c44
-rw-r--r--firmware/WHENCE10
-rw-r--r--fs/affs/super.c2
-rw-r--r--fs/afs/cmservice.c19
-rw-r--r--fs/afs/internal.h2
-rw-r--r--fs/afs/rxrpc.c86
-rw-r--r--fs/aio.c42
-rw-r--r--fs/autofs4/root.c4
-rw-r--r--fs/btrfs/ctree.h14
-rw-r--r--fs/btrfs/disk-io.c10
-rw-r--r--fs/btrfs/extent-tree.c6
-rw-r--r--fs/btrfs/file.c8
-rw-r--r--fs/btrfs/inode-map.c24
-rw-r--r--fs/btrfs/ioctl.c10
-rw-r--r--fs/btrfs/send.c7
-rw-r--r--fs/btrfs/super.c22
-rw-r--r--fs/ceph/caps.c2
-rw-r--r--fs/ceph/dir.c33
-rw-r--r--fs/ceph/file.c3
-rw-r--r--fs/ceph/inode.c71
-rw-r--r--fs/ceph/ioctl.c3
-rw-r--r--fs/ceph/locks.c1
-rw-r--r--fs/ceph/super.h1
-rw-r--r--fs/cifs/cifsfs.c14
-rw-r--r--fs/cifs/cifsglob.h8
-rw-r--r--fs/cifs/cifsproto.h3
-rw-r--r--fs/cifs/cifssmb.c3
-rw-r--r--fs/cifs/file.c35
-rw-r--r--fs/cifs/inode.c3
-rw-r--r--fs/cifs/misc.c74
-rw-r--r--fs/cifs/smb1ops.c11
-rw-r--r--fs/cifs/smb2misc.c18
-rw-r--r--fs/cifs/smb2ops.c14
-rw-r--r--fs/cifs/smb2pdu.c2
-rw-r--r--fs/compat.c14
-rw-r--r--fs/coredump.c7
-rw-r--r--fs/dcache.c433
-rw-r--r--fs/exec.c6
-rw-r--r--fs/ext4/balloc.c2
-rw-r--r--fs/ext4/ext4.h17
-rw-r--r--fs/ext4/extents.c109
-rw-r--r--fs/ext4/extents_status.c2
-rw-r--r--fs/ext4/file.c2
-rw-r--r--fs/ext4/inode.c53
-rw-r--r--fs/ext4/mballoc.c18
-rw-r--r--fs/ext4/page-io.c5
-rw-r--r--fs/ext4/super.c51
-rw-r--r--fs/ext4/xattr.c23
-rw-r--r--fs/fcntl.c12
-rw-r--r--fs/fuse/control.c2
-rw-r--r--fs/fuse/dir.c146
-rw-r--r--fs/fuse/file.c84
-rw-r--r--fs/fuse/fuse_i.h10
-rw-r--r--fs/fuse/inode.c16
-rw-r--r--fs/hugetlbfs/inode.c5
-rw-r--r--fs/kernfs/dir.c9
-rw-r--r--fs/kernfs/file.c19
-rw-r--r--fs/kernfs/inode.c14
-rw-r--r--fs/locks.c91
-rw-r--r--fs/namei.c6
-rw-r--r--fs/nfsd/nfs4acl.c19
-rw-r--r--fs/nfsd/nfs4callback.c4
-rw-r--r--fs/nfsd/nfs4state.c40
-rw-r--r--fs/nfsd/nfs4xdr.c8
-rw-r--r--fs/notify/fanotify/fanotify_user.c2
-rw-r--r--fs/ocfs2/dlm/dlmmaster.c8
-rw-r--r--fs/open.c21
-rw-r--r--fs/posix_acl.c6
-rw-r--r--fs/splice.c6
-rw-r--r--fs/super.c5
-rw-r--r--fs/sysfs/file.c95
-rw-r--r--fs/sysfs/mount.c3
-rw-r--r--fs/ubifs/super.c2
-rw-r--r--fs/xfs/xfs_aops.c51
-rw-r--r--fs/xfs/xfs_attr.c24
-rw-r--r--fs/xfs/xfs_attr_leaf.c21
-rw-r--r--fs/xfs/xfs_attr_list.c1
-rw-r--r--fs/xfs/xfs_attr_remote.c8
-rw-r--r--fs/xfs/xfs_bmap.c17
-rw-r--r--fs/xfs/xfs_bmap_util.c13
-rw-r--r--fs/xfs/xfs_buf.c16
-rw-r--r--fs/xfs/xfs_da_btree.h2
-rw-r--r--fs/xfs/xfs_export.c2
-rw-r--r--fs/xfs/xfs_file.c18
-rw-r--r--fs/xfs/xfs_inode.c5
-rw-r--r--fs/xfs/xfs_inode.h2
-rw-r--r--fs/xfs/xfs_iops.c53
-rw-r--r--fs/xfs/xfs_log.c63
-rw-r--r--fs/xfs/xfs_mount.c2
-rw-r--r--fs/xfs/xfs_qm.c26
-rw-r--r--fs/xfs/xfs_sb.c4
-rw-r--r--fs/xfs/xfs_super.c4
-rw-r--r--fs/xfs/xfs_trace.h1
-rw-r--r--include/asm-generic/fixmap.h3
-rw-r--r--include/asm-generic/pgtable.h31
-rw-r--r--include/asm-generic/resource.h2
-rw-r--r--include/asm-generic/word-at-a-time.h8
-rw-r--r--include/drm/drm_crtc_helper.h6
-rw-r--r--include/drm/drm_dp_helper.h4
-rw-r--r--include/drm/drm_pciids.h16
-rw-r--r--include/drm/i915_pciids.h4
-rw-r--r--include/dt-bindings/clock/at91.h (renamed from include/dt-bindings/clk/at91.h)0
-rw-r--r--include/dt-bindings/clock/tegra124-car.h6
-rw-r--r--include/linux/amba/bus.h1
-rw-r--r--include/linux/amba/mmci.h42
-rw-r--r--include/linux/cgroup.h15
-rw-r--r--include/linux/dcache.h2
-rw-r--r--include/linux/device.h11
-rw-r--r--include/linux/dmaengine.h1
-rw-r--r--include/linux/filter.h1
-rw-r--r--include/linux/fs.h2
-rw-r--r--include/linux/ftrace.h2
-rw-r--r--include/linux/gpio/consumer.h41
-rw-r--r--include/linux/gpio/driver.h5
-rw-r--r--include/linux/hsi/hsi.h39
-rw-r--r--include/linux/hsi/ssi_protocol.h42
-rw-r--r--include/linux/hugetlb.h10
-rw-r--r--include/linux/hyperv.h4
-rw-r--r--include/linux/if_macvlan.h1
-rw-r--r--include/linux/if_vlan.h15
-rw-r--r--include/linux/interrupt.h40
-rw-r--r--include/linux/ipmi.h2
-rw-r--r--include/linux/ipmi_smi.h11
-rw-r--r--include/linux/irq.h5
-rw-r--r--include/linux/kernfs.h19
-rw-r--r--include/linux/libata.h1
-rw-r--r--include/linux/linkage.h4
-rw-r--r--include/linux/mdio-gpio.h5
-rw-r--r--include/linux/mfd/rtsx_common.h1
-rw-r--r--include/linux/mfd/rtsx_pci.h6
-rw-r--r--include/linux/mfd/tc3589x.h1
-rw-r--r--include/linux/mlx4/qp.h11
-rw-r--r--include/linux/mlx5/device.h1
-rw-r--r--include/linux/mlx5/qp.h1
-rw-r--r--include/linux/mm.h2
-rw-r--r--include/linux/mtd/spear_smi.h2
-rw-r--r--include/linux/net.h15
-rw-r--r--include/linux/netdevice.h34
-rw-r--r--include/linux/netfilter/nf_conntrack_proto_gre.h1
-rw-r--r--include/linux/netlink.h7
-rw-r--r--include/linux/of.h7
-rw-r--r--include/linux/of_gpio.h35
-rw-r--r--include/linux/of_irq.h5
-rw-r--r--include/linux/of_mdio.h7
-rw-r--r--include/linux/omap-dma.h2
-rw-r--r--include/linux/perf_event.h2
-rw-r--r--include/linux/phy.h3
-rw-r--r--include/linux/phy/phy.h16
-rw-r--r--include/linux/reboot.h14
-rw-r--r--include/linux/regulator/consumer.h4
-rw-r--r--include/linux/rtnetlink.h5
-rw-r--r--include/linux/sched.h9
-rw-r--r--include/linux/serio.h1
-rw-r--r--include/linux/slub_def.h9
-rw-r--r--include/linux/sock_diag.h2
-rw-r--r--include/linux/sysfs.h9
-rw-r--r--include/linux/wait.h14
-rw-r--r--include/net/af_vsock.h6
-rw-r--r--include/net/cfg80211.h12
-rw-r--r--include/net/dst.h14
-rw-r--r--include/net/flow.h10
-rw-r--r--include/net/inet6_connection_sock.h2
-rw-r--r--include/net/inet_connection_sock.h2
-rw-r--r--include/net/ip.h13
-rw-r--r--include/net/ip6_route.h6
-rw-r--r--include/net/ip_tunnels.h2
-rw-r--r--include/net/ipv6.h2
-rw-r--r--include/net/net_namespace.h9
-rw-r--r--include/net/netfilter/nf_tables_core.h10
-rw-r--r--include/net/netns/ipv4.h9
-rw-r--r--include/net/sctp/structs.h18
-rw-r--r--include/net/sock.h5
-rw-r--r--include/net/xfrm.h6
-rw-r--r--include/trace/events/ext4.h9
-rw-r--r--include/trace/events/module.h4
-rw-r--r--include/uapi/asm-generic/fcntl.h20
-rw-r--r--include/uapi/asm-generic/resource.h7
-rw-r--r--include/uapi/asm-generic/unistd.h4
-rw-r--r--include/uapi/drm/tegra_drm.h1
-rw-r--r--include/uapi/linux/audit.h12
-rw-r--r--include/uapi/linux/fuse.h22
-rw-r--r--include/uapi/linux/hyperv.h1
-rw-r--r--include/uapi/linux/input.h1
-rw-r--r--include/uapi/linux/nl80211.h4
-rw-r--r--include/xen/interface/xen.h6
-rw-r--r--include/xen/xen-ops.h4
-rw-r--r--init/Kconfig24
-rw-r--r--init/main.c2
-rw-r--r--kernel/audit.c4
-rw-r--r--kernel/cgroup.c10
-rw-r--r--kernel/cgroup_freezer.c116
-rw-r--r--kernel/context_tracking.c2
-rw-r--r--kernel/cpu.c6
-rw-r--r--kernel/events/core.c174
-rw-r--r--kernel/futex.c52
-rw-r--r--kernel/hrtimer.c30
-rw-r--r--kernel/irq/irqdesc.c7
-rw-r--r--kernel/irq/manage.c17
-rw-r--r--kernel/kexec.c8
-rw-r--r--kernel/locking/lockdep.c2
-rw-r--r--kernel/locking/mutex-debug.c19
-rw-r--r--kernel/locking/rtmutex.c32
-rw-r--r--kernel/module.c6
-rw-r--r--kernel/power/snapshot.c2
-rw-r--r--kernel/power/suspend.c3
-rw-r--r--kernel/printk/printk.c4
-rw-r--r--kernel/sched/core.c80
-rw-r--r--kernel/sched/cpudeadline.c37
-rw-r--r--kernel/sched/cpudeadline.h6
-rw-r--r--kernel/sched/cpupri.c10
-rw-r--r--kernel/sched/cpupri.h2
-rw-r--r--kernel/sched/cputime.c32
-rw-r--r--kernel/sched/deadline.c16
-rw-r--r--kernel/sched/fair.c32
-rw-r--r--kernel/sched/rt.c7
-rw-r--r--kernel/sched/sched.h9
-rw-r--r--kernel/seccomp.c19
-rw-r--r--kernel/softirq.c9
-rw-r--r--kernel/time/tick-common.c2
-rw-r--r--kernel/time/tick-sched.c5
-rw-r--r--kernel/timer.c2
-rw-r--r--kernel/trace/ftrace.c27
-rw-r--r--kernel/trace/trace_events_trigger.c2
-rw-r--r--kernel/trace/trace_functions.c16
-rw-r--r--kernel/trace/trace_uprobe.c6
-rw-r--r--kernel/tracepoint.c4
-rw-r--r--kernel/user_namespace.c11
-rw-r--r--kernel/watchdog.c6
-rw-r--r--kernel/workqueue.c36
-rw-r--r--lib/Kconfig.debug3
-rw-r--r--lib/dump_stack.c4
-rw-r--r--mm/Kconfig15
-rw-r--r--mm/compaction.c22
-rw-r--r--mm/filemap.c56
-rw-r--r--mm/huge_memory.c13
-rw-r--r--mm/hugetlb.c20
-rw-r--r--mm/kmemleak.c4
-rw-r--r--mm/madvise.c2
-rw-r--r--mm/memcontrol.c47
-rw-r--r--mm/memory-failure.c17
-rw-r--r--mm/memory.c58
-rw-r--r--mm/mremap.c9
-rw-r--r--mm/page-writeback.c6
-rw-r--r--mm/percpu.c2
-rw-r--r--mm/slab.c6
-rw-r--r--mm/slab.h1
-rw-r--r--mm/slab_common.c13
-rw-r--r--mm/slub.c41
-rw-r--r--mm/truncate.c8
-rw-r--r--mm/util.c10
-rw-r--r--mm/vmacache.c8
-rw-r--r--mm/vmscan.c20
-rw-r--r--net/8021q/vlan.c1
-rw-r--r--net/8021q/vlan_dev.c12
-rw-r--r--net/batman-adv/bat_iv_ogm.c2
-rw-r--r--net/batman-adv/distributed-arp-table.c3
-rw-r--r--net/batman-adv/fragmentation.c11
-rw-r--r--net/batman-adv/gateway_client.c11
-rw-r--r--net/batman-adv/hard-interface.c2
-rw-r--r--net/batman-adv/originator.c62
-rw-r--r--net/bluetooth/hci_conn.c9
-rw-r--r--net/bluetooth/hci_event.c6
-rw-r--r--net/bridge/br_netfilter.c4
-rw-r--r--net/bridge/br_netlink.c15
-rw-r--r--net/can/gw.c4
-rw-r--r--net/ceph/messenger.c20
-rw-r--r--net/ceph/osdmap.c14
-rw-r--r--net/core/dev.c103
-rw-r--r--net/core/dst.c15
-rw-r--r--net/core/filter.c25
-rw-r--r--net/core/neighbour.c4
-rw-r--r--net/core/net_namespace.c2
-rw-r--r--net/core/rtnetlink.c86
-rw-r--r--net/core/skbuff.c4
-rw-r--r--net/core/sock.c49
-rw-r--r--net/core/sock_diag.c4
-rw-r--r--net/core/utils.c8
-rw-r--r--net/dcb/dcbnl.c2
-rw-r--r--net/dccp/output.c2
-rw-r--r--net/decnet/dn_dev.c4
-rw-r--r--net/decnet/dn_fib.c4
-rw-r--r--net/decnet/dn_route.c16
-rw-r--r--net/decnet/netfilter/dn_rtmsg.c2
-rw-r--r--net/dsa/dsa.c3
-rw-r--r--net/ipv4/af_inet.c36
-rw-r--r--net/ipv4/fib_frontend.c2
-rw-r--r--net/ipv4/fib_semantics.c3
-rw-r--r--net/ipv4/inet_connection_sock.c8
-rw-r--r--net/ipv4/ip_forward.c54
-rw-r--r--net/ipv4/ip_fragment.c5
-rw-r--r--net/ipv4/ip_output.c67
-rw-r--r--net/ipv4/ip_tunnel.c23
-rw-r--r--net/ipv4/ip_tunnel_core.c4
-rw-r--r--net/ipv4/ip_vti.c5
-rw-r--r--net/ipv4/ipmr.c2
-rw-r--r--net/ipv4/netfilter/ipt_rpfilter.c5
-rw-r--r--net/ipv4/netfilter/nf_defrag_ipv4.c5
-rw-r--r--net/ipv4/ping.c21
-rw-r--r--net/ipv4/route.c11
-rw-r--r--net/ipv4/sysctl_net_ipv4.c42
-rw-r--r--net/ipv4/tcp_cubic.c2
-rw-r--r--net/ipv4/tcp_output.c16
-rw-r--r--net/ipv4/xfrm4_output.c34
-rw-r--r--net/ipv4/xfrm4_protocol.c19
-rw-r--r--net/ipv6/inet6_connection_sock.c3
-rw-r--r--net/ipv6/ip6_fib.c3
-rw-r--r--net/ipv6/ip6_gre.c10
-rw-r--r--net/ipv6/ip6_offload.c6
-rw-r--r--net/ipv6/ip6_output.c10
-rw-r--r--net/ipv6/ip6_tunnel.c10
-rw-r--r--net/ipv6/ip6_vti.c8
-rw-r--r--net/ipv6/ip6mr.c4
-rw-r--r--net/ipv6/ndisc.c7
-rw-r--r--net/ipv6/netfilter.c6
-rw-r--r--net/ipv6/netfilter/ip6t_rpfilter.c1
-rw-r--r--net/ipv6/route.c45
-rw-r--r--net/ipv6/sit.c22
-rw-r--r--net/ipv6/tcpv6_offload.c2
-rw-r--r--net/ipv6/xfrm6_output.c24
-rw-r--r--net/ipv6/xfrm6_protocol.c11
-rw-r--r--net/iucv/af_iucv.c2
-rw-r--r--net/l2tp/l2tp_core.c4
-rw-r--r--net/l2tp/l2tp_ip.c2
-rw-r--r--net/mac80211/chan.c11
-rw-r--r--net/mac80211/ieee80211_i.h1
-rw-r--r--net/mac80211/main.c4
-rw-r--r--net/mac80211/mlme.c20
-rw-r--r--net/mac80211/offchannel.c26
-rw-r--r--net/mac80211/rx.c3
-rw-r--r--net/mac80211/sta_info.c3
-rw-r--r--net/mac80211/status.c6
-rw-r--r--net/mac80211/trace.h4
-rw-r--r--net/mac80211/util.c2
-rw-r--r--net/mac80211/vht.c9
-rw-r--r--net/netfilter/nf_conntrack_core.c1
-rw-r--r--net/netfilter/nf_conntrack_netlink.c3
-rw-r--r--net/netfilter/nf_conntrack_pptp.c20
-rw-r--r--net/netfilter/nf_conntrack_proto_gre.c3
-rw-r--r--net/netfilter/nf_tables_core.c52
-rw-r--r--net/netfilter/nfnetlink.c11
-rw-r--r--net/netfilter/nft_cmp.c2
-rw-r--r--net/netlink/af_netlink.c75
-rw-r--r--net/netlink/genetlink.c2
-rw-r--r--net/openvswitch/vport-gre.c2
-rw-r--r--net/packet/diag.c7
-rw-r--r--net/phonet/pn_netlink.c8
-rw-r--r--net/rxrpc/ar-key.c2
-rw-r--r--net/sched/act_api.c2
-rw-r--r--net/sched/cls_api.c2
-rw-r--r--net/sched/cls_tcindex.c30
-rw-r--r--net/sched/sch_api.c6
-rw-r--r--net/sched/sch_hhf.c11
-rw-r--r--net/sctp/associola.c82
-rw-r--r--net/sctp/auth.c17
-rw-r--r--net/sctp/endpointola.c3
-rw-r--r--net/sctp/protocol.c9
-rw-r--r--net/sctp/sm_make_chunk.c32
-rw-r--r--net/sctp/sm_sideeffect.c7
-rw-r--r--net/sctp/sm_statefuns.c8
-rw-r--r--net/sctp/socket.c60
-rw-r--r--net/sctp/sysctl.c36
-rw-r--r--net/sctp/ulpevent.c8
-rw-r--r--net/socket.c4
-rw-r--r--net/tipc/netlink.c2
-rw-r--r--net/vmw_vsock/af_vsock.c47
-rw-r--r--net/wireless/scan.c12
-rw-r--r--net/wireless/sme.c2
-rw-r--r--net/xfrm/xfrm_policy.c2
-rw-r--r--net/xfrm/xfrm_user.c2
-rwxr-xr-xscripts/checksyscalls.sh5
-rw-r--r--scripts/sortextable.c5
-rw-r--r--security/apparmor/include/apparmor.h1
-rw-r--r--security/apparmor/lib.c14
-rw-r--r--security/device_cgroup.c202
-rw-r--r--security/selinux/hooks.c6
-rw-r--r--sound/core/pcm_dmaengine.c6
-rw-r--r--sound/isa/es18xx.c10
-rw-r--r--sound/isa/sb/sb_mixer.c14
-rw-r--r--sound/pci/hda/hda_controller.c34
-rw-r--r--sound/pci/hda/hda_intel.c12
-rw-r--r--sound/pci/hda/hda_priv.h1
-rw-r--r--sound/pci/hda/patch_hdmi.c6
-rw-r--r--sound/pci/hda/patch_realtek.c10
-rw-r--r--sound/soc/codecs/alc5623.c2
-rw-r--r--sound/soc/codecs/cs42l52.c6
-rw-r--r--sound/soc/codecs/cs42l73.c6
-rw-r--r--sound/soc/codecs/tlv320aic31xx.c2
-rw-r--r--sound/soc/codecs/tlv320aic3x.c9
-rw-r--r--sound/soc/codecs/wm8962.c15
-rw-r--r--sound/soc/codecs/wm8962.h4
-rw-r--r--sound/soc/fsl/fsl_esai.c22
-rw-r--r--sound/soc/fsl/fsl_spdif.h4
-rw-r--r--sound/soc/fsl/imx-audmux.c2
-rw-r--r--sound/soc/intel/sst-acpi.c1
-rw-r--r--sound/soc/intel/sst-baytrail-dsp.c2
-rw-r--r--sound/soc/intel/sst-baytrail-ipc.c8
-rw-r--r--sound/soc/intel/sst-dsp-priv.h3
-rw-r--r--sound/soc/intel/sst-dsp.c1
-rw-r--r--sound/soc/intel/sst-dsp.h1
-rw-r--r--sound/soc/intel/sst-firmware.c25
-rw-r--r--sound/soc/intel/sst-haswell-dsp.c4
-rw-r--r--sound/soc/intel/sst-haswell-ipc.c38
-rw-r--r--sound/soc/intel/sst-haswell-ipc.h4
-rw-r--r--sound/soc/intel/sst-haswell-pcm.c107
-rw-r--r--sound/soc/jz4740/Makefile2
-rw-r--r--sound/soc/sh/rcar/core.c5
-rw-r--r--sound/soc/sh/rcar/src.c4
-rw-r--r--sound/soc/sh/rcar/ssi.c4
-rw-r--r--sound/soc/soc-dapm.c15
-rw-r--r--sound/soc/soc-pcm.c2
-rw-r--r--sound/usb/card.c12
-rw-r--r--sound/usb/card.h1
-rw-r--r--sound/usb/endpoint.c15
-rw-r--r--sound/usb/pcm.c5
-rw-r--r--sound/usb/usbaudio.h1
-rw-r--r--tools/Makefile6
-rw-r--r--tools/hv/hv_fcopy_daemon.c4
-rw-r--r--tools/lib/api/fs/debugfs.c4
-rw-r--r--tools/lib/lockdep/Makefile18
-rw-r--r--tools/lib/lockdep/uinclude/linux/lockdep.h3
-rw-r--r--tools/lib/traceevent/event-parse.c110
-rw-r--r--tools/lib/traceevent/event-parse.h4
-rw-r--r--tools/net/bpf_dbg.c2
-rw-r--r--tools/perf/Documentation/perf-bench.txt22
-rw-r--r--tools/perf/Documentation/perf-top.txt1
-rw-r--r--tools/perf/Makefile.perf6
-rw-r--r--tools/perf/arch/x86/tests/dwarf-unwind.c3
-rw-r--r--tools/perf/arch/x86/tests/regs_load.S8
-rw-r--r--tools/perf/bench/numa.c4
-rw-r--r--tools/perf/builtin-kvm.c1
-rw-r--r--tools/perf/builtin-record.c2
-rw-r--r--tools/perf/builtin-stat.c11
-rw-r--r--tools/perf/config/Makefile53
-rw-r--r--tools/perf/tests/code-reading.c1
-rw-r--r--tools/perf/tests/make2
-rw-r--r--tools/perf/util/data.c9
-rw-r--r--tools/perf/util/machine.c16
-rw-r--r--tools/perf/util/probe-finder.c15
-rw-r--r--tools/perf/util/symbol-elf.c2
-rw-r--r--tools/power/acpi/Makefile11
-rw-r--r--virt/kvm/arm/vgic.c15
-rw-r--r--virt/kvm/assigned-dev.c3
-rw-r--r--virt/kvm/async_pf.c8
-rw-r--r--virt/kvm/ioapic.c25
2158 files changed, 29233 insertions, 37159 deletions
diff --git a/.mailmap b/.mailmap
index 658003aa9446..df1baba43a64 100644
--- a/.mailmap
+++ b/.mailmap
@@ -99,6 +99,7 @@ Sachin P Sant <ssant@in.ibm.com>
Sam Ravnborg <sam@mars.ravnborg.org>
Sascha Hauer <s.hauer@pengutronix.de>
S.Çağlar Onur <caglar@pardus.org.tr>
+Shiraz Hashim <shiraz.linux.kernel@gmail.com> <shiraz.hashim@st.com>
Simon Kelley <simon@thekelleys.org.uk>
Stéphane Witzmann <stephane.witzmann@ubpmes.univ-bpclermont.fr>
Stephen Hemminger <shemminger@osdl.org>
diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci
index a3c5a6685036..ab8d76dfaa80 100644
--- a/Documentation/ABI/testing/sysfs-bus-pci
+++ b/Documentation/ABI/testing/sysfs-bus-pci
@@ -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
diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl
index f5170082bdb3..cc63f30de166 100644
--- a/Documentation/DocBook/device-drivers.tmpl
+++ b/Documentation/DocBook/device-drivers.tmpl
@@ -276,7 +276,7 @@ X!Isound/sound_firmware.c
</para>
<sect1><title>Frame Buffer Memory</title>
-!Edrivers/video/fbmem.c
+!Edrivers/video/fbdev/core/fbmem.c
</sect1>
<!--
<sect1><title>Frame Buffer Console</title>
@@ -284,7 +284,7 @@ X!Edrivers/video/console/fbcon.c
</sect1>
-->
<sect1><title>Frame Buffer Colormap</title>
-!Edrivers/video/fbcmap.c
+!Edrivers/video/fbdev/core/fbcmap.c
</sect1>
<!-- FIXME:
drivers/video/fbgen.c has no docs, which stuffs up the sgml. Comment
@@ -294,11 +294,11 @@ X!Idrivers/video/fbgen.c
</sect1>
KAO -->
<sect1><title>Frame Buffer Video Mode Database</title>
-!Idrivers/video/modedb.c
-!Edrivers/video/modedb.c
+!Idrivers/video/fbdev/core/modedb.c
+!Edrivers/video/fbdev/core/modedb.c
</sect1>
<sect1><title>Frame Buffer Macintosh Video Mode Database</title>
-!Edrivers/video/macmodes.c
+!Edrivers/video/fbdev/macmodes.c
</sect1>
<sect1><title>Frame Buffer Fonts</title>
<para>
diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl
index 702c4474919c..ba60d93c1855 100644
--- a/Documentation/DocBook/drm.tmpl
+++ b/Documentation/DocBook/drm.tmpl
@@ -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
@@ -2287,6 +2287,11 @@ void intel_crt_init(struct drm_device *dev)
!Edrivers/gpu/drm/drm_crtc_helper.c
</sect2>
<sect2>
+ <title>Output Probing Helper Functions Reference</title>
+!Pdrivers/gpu/drm/drm_probe_helper.c output probing helper overview
+!Edrivers/gpu/drm/drm_probe_helper.c
+ </sect2>
+ <sect2>
<title>fbdev Helper Functions Reference</title>
!Pdrivers/gpu/drm/drm_fb_helper.c fbdev helpers
!Edrivers/gpu/drm/drm_fb_helper.c
@@ -2351,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>
@@ -2692,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>
diff --git a/Documentation/DocBook/media/Makefile b/Documentation/DocBook/media/Makefile
index f9fd615427fb..1d27f0a1abd1 100644
--- a/Documentation/DocBook/media/Makefile
+++ b/Documentation/DocBook/media/Makefile
@@ -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 $< >$@
diff --git a/Documentation/acpi/enumeration.txt b/Documentation/acpi/enumeration.txt
index 2a1519b87177..fd786ea13a1f 100644
--- a/Documentation/acpi/enumeration.txt
+++ b/Documentation/acpi/enumeration.txt
@@ -296,7 +296,7 @@ specifies the path to the controller. In order to use these GPIOs in Linux
we need to translate them to the corresponding Linux GPIO descriptors.
There is a standard GPIO API for that and is documented in
-Documentation/gpio.txt.
+Documentation/gpio/.
In the above example we can get the corresponding two GPIO descriptors with
a code like this:
diff --git a/Documentation/debugging-via-ohci1394.txt b/Documentation/debugging-via-ohci1394.txt
index fa0151a712f9..5c9a567b3fac 100644
--- a/Documentation/debugging-via-ohci1394.txt
+++ b/Documentation/debugging-via-ohci1394.txt
@@ -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:
diff --git a/Documentation/device-mapper/thin-provisioning.txt b/Documentation/device-mapper/thin-provisioning.txt
index 05a27e9442bd..2f5173500bd9 100644
--- a/Documentation/device-mapper/thin-provisioning.txt
+++ b/Documentation/device-mapper/thin-provisioning.txt
@@ -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
diff --git a/Documentation/devicetree/bindings/arm/arch_timer.txt b/Documentation/devicetree/bindings/arm/arch_timer.txt
index 06fc7602593a..37b2cafa4e52 100644
--- a/Documentation/devicetree/bindings/arm/arch_timer.txt
+++ b/Documentation/devicetree/bindings/arm/arch_timer.txt
@@ -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 {
diff --git a/Documentation/devicetree/bindings/arm/marvell,kirkwood.txt b/Documentation/devicetree/bindings/arm/marvell,kirkwood.txt
new file mode 100644
index 000000000000..925ecbf6e7b7
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/marvell,kirkwood.txt
@@ -0,0 +1,97 @@
+Marvell Kirkwood SoC Family Device Tree Bindings
+------------------------------------------------
+
+Boards with a SoC of the Marvell Kirkwook family, eg 88f6281
+
+* Required root node properties:
+compatible: must contain "marvell,kirkwood"
+
+In addition, the above compatible shall be extended with the specific
+SoC. Currently known SoC compatibles are:
+
+"marvell,kirkwood-88f6192"
+"marvell,kirkwood-88f6281"
+"marvell,kirkwood-88f6282"
+"marvell,kirkwood-88f6283"
+"marvell,kirkwood-88f6702"
+"marvell,kirkwood-98DX4122"
+
+And in addition, the compatible shall be extended with the specific
+board. Currently known boards are:
+
+"buffalo,lschlv2"
+"buffalo,lsxhl"
+"buffalo,lsxl"
+"dlink,dns-320"
+"dlink,dns-320-a1"
+"dlink,dns-325"
+"dlink,dns-325-a1"
+"dlink,dns-kirkwood"
+"excito,b3"
+"globalscale,dreamplug-003-ds2001"
+"globalscale,guruplug"
+"globalscale,guruplug-server-plus"
+"globalscale,sheevaplug"
+"globalscale,sheevaplug"
+"globalscale,sheevaplug-esata"
+"globalscale,sheevaplug-esata-rev13"
+"iom,iconnect"
+"iom,iconnect-1.1"
+"iom,ix2-200"
+"keymile,km_kirkwood"
+"lacie,cloudbox"
+"lacie,inetspace_v2"
+"lacie,laplug"
+"lacie,netspace_lite_v2"
+"lacie,netspace_max_v2"
+"lacie,netspace_mini_v2"
+"lacie,netspace_v2"
+"marvell,db-88f6281-bp"
+"marvell,db-88f6282-bp"
+"marvell,mv88f6281gtw-ge"
+"marvell,rd88f6281"
+"marvell,rd88f6281"
+"marvell,rd88f6281-a0"
+"marvell,rd88f6281-a1"
+"mpl,cec4"
+"mpl,cec4-10"
+"netgear,readynas"
+"netgear,readynas"
+"netgear,readynas-duo-v2"
+"netgear,readynas-nv+-v2"
+"plathome,openblocks-a6"
+"plathome,openblocks-a7"
+"raidsonic,ib-nas6210"
+"raidsonic,ib-nas6210-b"
+"raidsonic,ib-nas6220"
+"raidsonic,ib-nas6220-b"
+"raidsonic,ib-nas62x0"
+"seagate,dockstar"
+"seagate,goflexnet"
+"synology,ds109"
+"synology,ds110jv10"
+"synology,ds110jv20"
+"synology,ds110jv30"
+"synology,ds111"
+"synology,ds209"
+"synology,ds210jv10"
+"synology,ds210jv20"
+"synology,ds212"
+"synology,ds212jv10"
+"synology,ds212jv20"
+"synology,ds212pv10"
+"synology,ds409"
+"synology,ds409slim"
+"synology,ds410j"
+"synology,ds411"
+"synology,ds411j"
+"synology,ds411slim"
+"synology,ds413jv10"
+"synology,rs212"
+"synology,rs409"
+"synology,rs411"
+"synology,rs812"
+"usi,topkick"
+"usi,topkick-1281P2"
+"zyxel,nsa310"
+"zyxel,nsa310a"
diff --git a/Documentation/devicetree/bindings/ata/apm-xgene.txt b/Documentation/devicetree/bindings/ata/apm-xgene.txt
index 7bcfbf59810e..a668f0e7d001 100644
--- a/Documentation/devicetree/bindings/ata/apm-xgene.txt
+++ b/Documentation/devicetree/bindings/ata/apm-xgene.txt
@@ -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>;
diff --git a/Documentation/devicetree/bindings/clock/at91-clock.txt b/Documentation/devicetree/bindings/clock/at91-clock.txt
index cd5e23912888..6794cdc96d8f 100644
--- a/Documentation/devicetree/bindings/clock/at91-clock.txt
+++ b/Documentation/devicetree/bindings/clock/at91-clock.txt
@@ -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
diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt
index 5992dceec7af..02a25d99ca61 100644
--- a/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt
+++ b/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt
@@ -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
diff --git a/Documentation/devicetree/bindings/dma/ti-edma.txt b/Documentation/devicetree/bindings/dma/ti-edma.txt
index 9fbbdb783a72..68ff2137bae7 100644
--- a/Documentation/devicetree/bindings/dma/ti-edma.txt
+++ b/Documentation/devicetree/bindings/dma/ti-edma.txt
@@ -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>;
};
diff --git a/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt b/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt
index f61cef74a212..941a26aa4322 100644
--- a/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt
+++ b/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt
@@ -21,6 +21,12 @@ Required Properties:
GPIO_ACTIVE_HIGH and GPIO_ACTIVE_LOW flags are supported.
- gpio-ranges: Range of pins managed by the GPIO controller.
+Optional properties:
+
+ - clocks: Must contain a reference to the functional clock. The property is
+ mandatory if the hardware implements a controllable functional clock for
+ the GPIO instance.
+
Please refer to gpio.txt in this directory for details of gpio-ranges property
and the common GPIO bindings used by client devices.
diff --git a/Documentation/devicetree/bindings/hsi/client-devices.txt b/Documentation/devicetree/bindings/hsi/client-devices.txt
new file mode 100644
index 000000000000..104c9a3e57a4
--- /dev/null
+++ b/Documentation/devicetree/bindings/hsi/client-devices.txt
@@ -0,0 +1,44 @@
+Each HSI port is supposed to have one child node, which
+symbols the remote device connected to the HSI port. The
+following properties are standardized for HSI clients:
+
+Required HSI configuration properties:
+
+- hsi-channel-ids: A list of channel ids
+
+- hsi-rx-mode: Receiver Bit transmission mode ("stream" or "frame")
+- hsi-tx-mode: Transmitter Bit transmission mode ("stream" or "frame")
+- hsi-mode: May be used instead hsi-rx-mode and hsi-tx-mode if
+ the transmission mode is the same for receiver and
+ transmitter
+- hsi-speed-kbps: Max bit transmission speed in kbit/s
+- hsi-flow: RX flow type ("synchronized" or "pipeline")
+- hsi-arb-mode: Arbitration mode for TX frame ("round-robin", "priority")
+
+Optional HSI configuration properties:
+
+- hsi-channel-names: A list with one name per channel specified in the
+ hsi-channel-ids property
+
+
+Device Tree node example for an HSI client:
+
+hsi-controller {
+ hsi-port {
+ modem: hsi-client {
+ compatible = "nokia,n900-modem";
+
+ hsi-channel-ids = <0>, <1>, <2>, <3>;
+ hsi-channel-names = "mcsaab-control",
+ "speech-control",
+ "speech-data",
+ "mcsaab-data";
+ hsi-speed-kbps = <55000>;
+ hsi-mode = "frame";
+ hsi-flow = "synchronized";
+ hsi-arb-mode = "round-robin";
+
+ /* more client specific properties */
+ };
+ };
+};
diff --git a/Documentation/devicetree/bindings/hsi/nokia-modem.txt b/Documentation/devicetree/bindings/hsi/nokia-modem.txt
new file mode 100644
index 000000000000..8a979780452b
--- /dev/null
+++ b/Documentation/devicetree/bindings/hsi/nokia-modem.txt
@@ -0,0 +1,57 @@
+Nokia modem client bindings
+
+The Nokia modem HSI client follows the common HSI client binding
+and inherits all required properties. The following additional
+properties are needed by the Nokia modem HSI client:
+
+Required properties:
+- compatible: Should be one of
+ "nokia,n900-modem"
+- hsi-channel-names: Should contain the following strings
+ "mcsaab-control"
+ "speech-control"
+ "speech-data"
+ "mcsaab-data"
+- gpios: Should provide a GPIO handler for each GPIO listed in
+ gpio-names
+- gpio-names: Should contain the following strings
+ "cmt_apeslpx"
+ "cmt_rst_rq"
+ "cmt_en"
+ "cmt_rst"
+ "cmt_bsi"
+- interrupts: Should be IRQ handle for modem's reset indication
+
+Example:
+
+&ssi_port {
+ modem: hsi-client {
+ compatible = "nokia,n900-modem";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&modem_pins>;
+
+ hsi-channel-ids = <0>, <1>, <2>, <3>;
+ hsi-channel-names = "mcsaab-control",
+ "speech-control",
+ "speech-data",
+ "mcsaab-data";
+ hsi-speed-kbps = <55000>;
+ hsi-mode = "frame";
+ hsi-flow = "synchronized";
+ hsi-arb-mode = "round-robin";
+
+ interrupts-extended = <&gpio3 8 IRQ_TYPE_EDGE_FALLING>; /* 72 */
+
+ gpios = <&gpio3 6 GPIO_ACTIVE_HIGH>, /* 70 */
+ <&gpio3 9 GPIO_ACTIVE_HIGH>, /* 73 */
+ <&gpio3 10 GPIO_ACTIVE_HIGH>, /* 74 */
+ <&gpio3 11 GPIO_ACTIVE_HIGH>, /* 75 */
+ <&gpio5 29 GPIO_ACTIVE_HIGH>; /* 157 */
+ gpio-names = "cmt_apeslpx",
+ "cmt_rst_rq",
+ "cmt_en",
+ "cmt_rst",
+ "cmt_bsi";
+ };
+};
diff --git a/Documentation/devicetree/bindings/hsi/omap-ssi.txt b/Documentation/devicetree/bindings/hsi/omap-ssi.txt
new file mode 100644
index 000000000000..f26625e42693
--- /dev/null
+++ b/Documentation/devicetree/bindings/hsi/omap-ssi.txt
@@ -0,0 +1,97 @@
+OMAP SSI controller bindings
+
+OMAP Synchronous Serial Interface (SSI) controller implements a legacy
+variant of MIPI's High Speed Synchronous Serial Interface (HSI).
+
+Required properties:
+- compatible: Should include "ti,omap3-ssi".
+- reg-names: Contains the values "sys" and "gdd" (in this order).
+- reg: Contains a matching register specifier for each entry
+ in reg-names.
+- interrupt-names: Contains the value "gdd_mpu".
+- interrupts: Contains matching interrupt information for each entry
+ in interrupt-names.
+- ranges: Represents the bus address mapping between the main
+ controller node and the child nodes below.
+- clock-names: Must include the following entries:
+ "ssi_ssr_fck": The OMAP clock of that name
+ "ssi_sst_fck": The OMAP clock of that name
+ "ssi_ick": The OMAP clock of that name
+- clocks: Contains a matching clock specifier for each entry in
+ clock-names.
+- #address-cells: Should be set to <1>
+- #size-cells: Should be set to <1>
+
+Each port is represented as a sub-node of the ti,omap3-ssi device.
+
+Required Port sub-node properties:
+- compatible: Should be set to the following value
+ ti,omap3-ssi-port (applicable to OMAP34xx devices)
+- reg-names: Contains the values "tx" and "rx" (in this order).
+- reg: Contains a matching register specifier for each entry
+ in reg-names.
+- interrupt-parent Should be a phandle for the interrupt controller
+- interrupts: Should contain interrupt specifiers for mpu interrupts
+ 0 and 1 (in this order).
+- ti,ssi-cawake-gpio: Defines which GPIO pin is used to signify CAWAKE
+ events for the port. This is an optional board-specific
+ property. If it's missing the port will not be
+ enabled.
+
+Example for Nokia N900:
+
+ssi-controller@48058000 {
+ compatible = "ti,omap3-ssi";
+
+ /* needed until hwmod is updated to use the compatible string */
+ ti,hwmods = "ssi";
+
+ reg = <0x48058000 0x1000>,
+ <0x48059000 0x1000>;
+ reg-names = "sys",
+ "gdd";
+
+ interrupts = <55>;
+ interrupt-names = "gdd_mpu";
+
+ clocks = <&ssi_ssr_fck>,
+ <&ssi_sst_fck>,
+ <&ssi_ick>;
+ clock-names = "ssi_ssr_fck",
+ "ssi_sst_fck",
+ "ssi_ick";
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ ssi-port@4805a000 {
+ compatible = "ti,omap3-ssi-port";
+
+ reg = <0x4805a000 0x800>,
+ <0x4805a800 0x800>;
+ reg-names = "tx",
+ "rx";
+
+ interrupt-parent = <&intc>;
+ interrupts = <67>,
+ <68>;
+
+ ti,ssi-cawake-gpio = <&gpio5 23 GPIO_ACTIVE_HIGH>; /* 151 */
+ }
+
+ ssi-port@4805a000 {
+ compatible = "ti,omap3-ssi-port";
+
+ reg = <0x4805b000 0x800>,
+ <0x4805b800 0x800>;
+ reg-names = "tx",
+ "rx";
+
+ interrupt-parent = <&intc>;
+ interrupts = <69>,
+ <70>;
+
+ status = "disabled"; /* second port is not used on N900 */
+ }
+}
diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
index 71724d026ffa..bef86e57c388 100644
--- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt
+++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
@@ -13,8 +13,22 @@ ad,ad7414 SMBus/I2C Digital Temperature Sensor in 6-Pin SOT with SMBus Alert an
ad,adm9240 ADM9240: Complete System Hardware Monitor for uProcessor-Based Systems
adi,adt7461 +/-1C TDM Extended Temp Range I.C
adt7461 +/-1C TDM Extended Temp Range I.C
+adi,adt7473 +/-1C TDM Extended Temp Range I.C
+adi,adt7475 +/-1C TDM Extended Temp Range I.C
+adi,adt7476 +/-1C TDM Extended Temp Range I.C
+adi,adt7490 +/-1C TDM Extended Temp Range I.C
at,24c08 i2c serial eeprom (24cxx)
+atmel,24c00 i2c serial eeprom (24cxx)
+atmel,24c01 i2c serial eeprom (24cxx)
atmel,24c02 i2c serial eeprom (24cxx)
+atmel,24c04 i2c serial eeprom (24cxx)
+atmel,24c16 i2c serial eeprom (24cxx)
+atmel,24c32 i2c serial eeprom (24cxx)
+atmel,24c64 i2c serial eeprom (24cxx)
+atmel,24c128 i2c serial eeprom (24cxx)
+atmel,24c256 i2c serial eeprom (24cxx)
+atmel,24c512 i2c serial eeprom (24cxx)
+atmel,24c1024 i2c serial eeprom (24cxx)
atmel,at97sc3204t i2c trusted platform module (TPM)
capella,cm32181 CM32181: Ambient Light Sensor
catalyst,24c32 i2c serial eeprom
@@ -46,8 +60,10 @@ maxim,ds1050 5 Bit Programmable, Pulse-Width Modulator
maxim,max1237 Low-Power, 4-/12-Channel, 2-Wire Serial, 12-Bit ADCs
maxim,max6625 9-Bit/12-Bit Temperature Sensors with I²C-Compatible Serial Interface
mc,rv3029c2 Real Time Clock Module with I2C-Bus
+national,lm63 Temperature sensor with integrated fan control
national,lm75 I2C TEMP SENSOR
national,lm80 Serial Interface ACPI-Compatible Microprocessor System Hardware Monitor
+national,lm85 Temperature sensor with integrated fan control
national,lm92 ±0.33°C Accurate, 12-Bit + Sign Temperature Sensor and Thermal Window Comparator with Two-Wire Interface
nuvoton,npct501 i2c trusted platform module (TPM)
nxp,pca9556 Octal SMBus and I2C registered interface
diff --git a/Documentation/devicetree/bindings/mmc/mmci.txt b/Documentation/devicetree/bindings/mmc/mmci.txt
index 2b584cae352a..03796cf2d3e7 100644
--- a/Documentation/devicetree/bindings/mmc/mmci.txt
+++ b/Documentation/devicetree/bindings/mmc/mmci.txt
@@ -4,12 +4,58 @@ The ARM PrimeCell MMCI PL180 and PL181 provides an interface for
reading and writing to MultiMedia and SD cards alike.
This file documents differences between the core properties described
-by mmc.txt and the properties used by the mmci driver.
+by mmc.txt and the properties used by the mmci driver. Using "st" as
+the prefix for a property, indicates support by the ST Micro variant.
Required properties:
- compatible : contains "arm,pl18x", "arm,primecell".
-- arm,primecell-periphid : contains the PrimeCell Peripheral ID.
+- vmmc-supply : phandle to the regulator device tree node, mentioned
+ as the VCC/VDD supply in the eMMC/SD specs.
Optional properties:
-- mmc-cap-mmc-highspeed : indicates whether MMC is high speed capable
-- mmc-cap-sd-highspeed : indicates whether SD is high speed capable
+- arm,primecell-periphid : contains the PrimeCell Peripheral ID, it overrides
+ the ID provided by the HW
+- vqmmc-supply : phandle to the regulator device tree node, mentioned
+ as the VCCQ/VDD_IO supply in the eMMC/SD specs.
+- st,sig-dir-dat0 : bus signal direction pin used for DAT[0].
+- st,sig-dir-dat2 : bus signal direction pin used for DAT[2].
+- st,sig-dir-dat31 : bus signal direction pin used for DAT[3] and DAT[1].
+- st,sig-dir-dat74 : bus signal direction pin used for DAT[4] to DAT[7].
+- st,sig-dir-cmd : cmd signal direction pin used for CMD.
+- st,sig-pin-fbclk : feedback clock signal pin used.
+
+Deprecated properties:
+- mmc-cap-mmc-highspeed : indicates whether MMC is high speed capable.
+- mmc-cap-sd-highspeed : indicates whether SD is high speed capable.
+
+Example:
+
+sdi0_per1@80126000 {
+ compatible = "arm,pl18x", "arm,primecell";
+ reg = <0x80126000 0x1000>;
+ interrupts = <0 60 IRQ_TYPE_LEVEL_HIGH>;
+
+ dmas = <&dma 29 0 0x2>, /* Logical - DevToMem */
+ <&dma 29 0 0x0>; /* Logical - MemToDev */
+ dma-names = "rx", "tx";
+
+ clocks = <&prcc_kclk 1 5>, <&prcc_pclk 1 5>;
+ clock-names = "sdi", "apb_pclk";
+
+ max-frequency = <100000000>;
+ bus-width = <4>;
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ cd-gpios = <&gpio2 31 0x4>; // 95
+ st,sig-dir-dat0;
+ st,sig-dir-dat2;
+ st,sig-dir-cmd;
+ st,sig-pin-fbclk;
+
+ vmmc-supply = <&ab8500_ldo_aux3_reg>;
+ vqmmc-supply = <&vmmci>;
+
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&sdi0_default_mode>;
+ pinctrl-1 = <&sdi0_sleep_mode>;
+};
diff --git a/Documentation/devicetree/bindings/net/arc_emac.txt b/Documentation/devicetree/bindings/net/arc_emac.txt
index 7fbb027218a1..a1d71eb43b20 100644
--- a/Documentation/devicetree/bindings/net/arc_emac.txt
+++ b/Documentation/devicetree/bindings/net/arc_emac.txt
@@ -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>;
diff --git a/Documentation/devicetree/bindings/net/ethernet.txt b/Documentation/devicetree/bindings/net/ethernet.txt
index 9ecd43d8792c..3fc360523bc9 100644
--- a/Documentation/devicetree/bindings/net/ethernet.txt
+++ b/Documentation/devicetree/bindings/net/ethernet.txt
@@ -10,7 +10,7 @@ The following properties are common to the Ethernet controllers:
- max-frame-size: number, maximum transfer unit (IEEE defined MTU), rather than
the maximum frame size (there's contradiction in ePAPR).
- phy-mode: string, operation mode of the PHY interface; supported values are
- "mii", "gmii", "sgmii", "tbi", "rev-mii", "rmii", "rgmii", "rgmii-id",
+ "mii", "gmii", "sgmii", "qsgmii", "tbi", "rev-mii", "rmii", "rgmii", "rgmii-id",
"rgmii-rxid", "rgmii-txid", "rtbi", "smii", "xgmii"; this is now a de-facto
standard property;
- phy-connection-type: the same as "phy-mode" property but described in ePAPR;
diff --git a/Documentation/devicetree/bindings/net/mdio-gpio.txt b/Documentation/devicetree/bindings/net/mdio-gpio.txt
index c79bab025369..8dbcf8295c6c 100644
--- a/Documentation/devicetree/bindings/net/mdio-gpio.txt
+++ b/Documentation/devicetree/bindings/net/mdio-gpio.txt
@@ -14,7 +14,7 @@ node.
Example:
aliases {
- mdio-gpio0 = <&mdio0>;
+ mdio-gpio0 = &mdio0;
};
mdio0: mdio {
diff --git a/Documentation/devicetree/bindings/net/socfpga-dwmac.txt b/Documentation/devicetree/bindings/net/socfpga-dwmac.txt
index 636f0ac4e223..2a60cd3e8d5d 100644
--- a/Documentation/devicetree/bindings/net/socfpga-dwmac.txt
+++ b/Documentation/devicetree/bindings/net/socfpga-dwmac.txt
@@ -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";
};
diff --git a/Documentation/devicetree/bindings/net/stmmac.txt b/Documentation/devicetree/bindings/net/stmmac.txt
index 80c1fb8bfbb8..a2acd2b26baf 100644
--- a/Documentation/devicetree/bindings/net/stmmac.txt
+++ b/Documentation/devicetree/bindings/net/stmmac.txt
@@ -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:
diff --git a/Documentation/devicetree/bindings/pinctrl/brcm,bcm11351-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/brcm,bcm11351-pinctrl.txt
index c119debe6bab..67a5db95f189 100644
--- a/Documentation/devicetree/bindings/pinctrl/brcm,bcm11351-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,bcm11351-pinctrl.txt
@@ -119,7 +119,7 @@ Optional Properties (for HDMI pins):
Example:
// pin controller node
pinctrl@35004800 {
- compatible = "brcmbcm11351-pinctrl";
+ compatible = "brcm,bcm11351-pinctrl";
reg = <0x35004800 0x430>;
// pin configuration node
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-st.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-st.txt
index 4bd5be0e5e7d..26bcb18f4e60 100644
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-st.txt
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-st.txt
@@ -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>;
};
diff --git a/Documentation/devicetree/bindings/serial/efm32-uart.txt b/Documentation/devicetree/bindings/serial/efm32-uart.txt
index 1984bdfbd545..3ca01336b837 100644
--- a/Documentation/devicetree/bindings/serial/efm32-uart.txt
+++ b/Documentation/devicetree/bindings/serial/efm32-uart.txt
@@ -1,7 +1,7 @@
* Energymicro efm32 UART
Required properties:
-- compatible : Should be "efm32,uart"
+- compatible : Should be "energymicro,efm32-uart"
- reg : Address and length of the register set
- interrupts : Should contain uart interrupt
@@ -13,7 +13,7 @@ Optional properties:
Example:
uart@0x4000c400 {
- compatible = "efm32,uart";
+ compatible = "energymicro,efm32-uart";
reg = <0x4000c400 0x400>;
interrupts = <15>;
efm32,location = <0>;
diff --git a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt
index 569b26c4a81e..60ca07996458 100644
--- a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt
+++ b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt
@@ -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 = <
diff --git a/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt b/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt
index 74c66dee3e14..eff12be5e789 100644
--- a/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt
+++ b/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt
@@ -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
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 0f01c9bf19c8..abc308083acb 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -22,6 +22,7 @@ auo AU Optronics Corporation
avago Avago Technologies
bosch Bosch Sensortec GmbH
brcm Broadcom Corporation
+buffalo Buffalo, Inc.
calxeda Calxeda
capella Capella Microsystems, Inc
cavium Cavium, Inc.
@@ -33,15 +34,18 @@ cortina Cortina Systems, Inc.
crystalfontz Crystalfontz America, Inc.
dallas Maxim Integrated Products (formerly Dallas Semiconductor)
davicom DAVICOM Semiconductor, Inc.
-dlink D-Link Systems, Inc.
denx Denx Software Engineering
+digi Digi International Inc.
+dlink D-Link Corporation
dmo Data Modul AG
+ebv EBV Elektronik
edt Emerging Display Technologies
emmicro EM Microelectronic
epfl Ecole Polytechnique Fédérale de Lausanne
epson Seiko Epson Corp.
est ESTeem Wireless Modems
eukrea Eukréa Electromatique
+excito Excito
fsl Freescale Semiconductor
GEFanuc GE Fanuc Intelligent Platforms Embedded Systems, Inc.
gef GE Fanuc Intelligent Platforms Embedded Systems, Inc.
@@ -53,13 +57,17 @@ haoyu Haoyu Microelectronic Co. Ltd.
hisilicon Hisilicon Limited.
honeywell Honeywell
hp Hewlett Packard
+i2se I2SE GmbH
ibm International Business Machines (IBM)
idt Integrated Device Technologies, Inc.
+iom Iomega Corporation
img Imagination Technologies Ltd.
intel Intel Corporation
intercontrol Inter Control Group
+isee ISEE 2007 S.L.
isl Intersil
karo Ka-Ro electronics GmbH
+keymile Keymile GmbH
lacie LaCie
lantiq Lantiq Semiconductor
lg LG Corporation
@@ -70,9 +78,12 @@ maxim Maxim Integrated Products
microchip Microchip Technology Inc.
mosaixtech Mosaix Technologies, Inc.
moxa Moxa
+mpl MPL AG
+mxicy Macronix International Co., Ltd.
national National Semiconductor
neonode Neonode Inc.
netgear NETGEAR
+newhaven Newhaven Display International
nintendo Nintendo
nokia Nokia
nvidia NVIDIA
@@ -82,10 +93,12 @@ opencores OpenCores.org
panasonic Panasonic Corporation
phytec PHYTEC Messtechnik GmbH
picochip Picochip Ltd
+plathome Plat'Home Co., Ltd.
powervr PowerVR (deprecated, use img)
qca Qualcomm Atheros, Inc.
qcom Qualcomm Technologies, Inc
qnap QNAP Systems, Inc.
+raidsonic RaidSonic Technology GmbH
ralink Mediatek/Ralink Technology Corp.
ramtron Ramtron International
realtek Realtek Semiconductor Corp.
@@ -95,6 +108,7 @@ rockchip Fuzhou Rockchip Electronics Co., Ltd
samsung Samsung Semiconductor
sbs Smart Battery System
schindler Schindler
+seagate Seagate Technology PLC
sil Silicon Image
silabs Silicon Laboratories
simtek
@@ -111,6 +125,7 @@ ti Texas Instruments
tlm Trusted Logic Mobility
toshiba Toshiba Corporation
toumaz Toumaz
+usi Universal Scientifc Industrial Co., Ltd.
v3 V3 Semiconductor
via VIA Technologies, Inc.
voipac Voipac Technologies s.r.o.
@@ -119,3 +134,4 @@ wlf Wolfson Microelectronics
wm Wondermedia Technologies, Inc.
xes Extreme Engineering Solutions (X-ES)
xlnx Xilinx
+zyxel ZyXEL Communications Corp.
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index 4f7897e99cba..10b8c5d2c797 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -308,3 +308,10 @@ SLAVE DMA ENGINE
SPI
devm_spi_register_master()
+
+GPIO
+ devm_gpiod_get()
+ devm_gpiod_get_index()
+ devm_gpiod_get_optional()
+ devm_gpiod_get_index_optional()
+ devm_gpiod_put()
diff --git a/Documentation/email-clients.txt b/Documentation/email-clients.txt
index e9f5daccbd02..4e30ebaa9e5b 100644
--- a/Documentation/email-clients.txt
+++ b/Documentation/email-clients.txt
@@ -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)
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index 8b9cd8eb3f91..264bcde0c51c 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -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.
diff --git a/Documentation/gpio/driver.txt b/Documentation/gpio/driver.txt
index f73cc7b5dc85..fa9a0a8b3734 100644
--- a/Documentation/gpio/driver.txt
+++ b/Documentation/gpio/driver.txt
@@ -73,6 +73,65 @@ The IRQ portions of the GPIO block are implemented using an irqchip, using
the header <linux/irq.h>. So basically such a driver is utilizing two sub-
systems simultaneously: gpio and irq.
+GPIO irqchips usually fall in one of two categories:
+
+* CHAINED GPIO irqchips: these are usually the type that is embedded on
+ an SoC. This means that there is a fast IRQ handler for the GPIOs that
+ gets called in a chain from the parent IRQ handler, most typically the
+ system interrupt controller. This means the GPIO irqchip is registered
+ using irq_set_chained_handler() or the corresponding
+ gpiochip_set_chained_irqchip() helper function, and the GPIO irqchip
+ handler will be called immediately from the parent irqchip, while
+ holding the IRQs disabled. The GPIO irqchip will then end up calling
+ something like this sequence in its interrupt handler:
+
+ static irqreturn_t tc3589x_gpio_irq(int irq, void *data)
+ chained_irq_enter(...);
+ generic_handle_irq(...);
+ chained_irq_exit(...);
+
+ Chained GPIO irqchips typically can NOT set the .can_sleep flag on
+ struct gpio_chip, as everything happens directly in the callbacks.
+
+* NESTED THREADED GPIO irqchips: these are off-chip GPIO expanders and any
+ other GPIO irqchip residing on the other side of a sleeping bus. Of course
+ such drivers that need slow bus traffic to read out IRQ status and similar,
+ traffic which may in turn incur other IRQs to happen, cannot be handled
+ in a quick IRQ handler with IRQs disabled. Instead they need to spawn a
+ thread and then mask the parent IRQ line until the interrupt is handled
+ by the driver. The hallmark of this driver is to call something like
+ this in its interrupt handler:
+
+ static irqreturn_t tc3589x_gpio_irq(int irq, void *data)
+ ...
+ handle_nested_irq(irq);
+
+ The hallmark of threaded GPIO irqchips is that they set the .can_sleep
+ flag on struct gpio_chip to true, indicating that this chip may sleep
+ when accessing the GPIOs.
+
+To help out in handling the set-up and management of GPIO irqchips and the
+associated irqdomain and resource allocation callbacks, the gpiolib has
+some helpers that can be enabled by selecting the GPIOLIB_IRQCHIP Kconfig
+symbol:
+
+* gpiochip_irqchip_add(): adds an irqchip to a gpiochip. It will pass
+ the struct gpio_chip* for the chip to all IRQ callbacks, so the callbacks
+ need to embed the gpio_chip in its state container and obtain a pointer
+ to the container using container_of().
+ (See Documentation/driver-model/design-patterns.txt)
+
+* gpiochip_set_chained_irqchip(): sets up a chained irq handler for a
+ gpio_chip from a parent IRQ and passes the struct gpio_chip* as handler
+ data. (Notice handler data, since the irqchip data is likely used by the
+ parent irqchip!) This is for the chained type of chip.
+
+To use the helpers please keep the following in mind:
+
+- Make sure to assign all relevant members of the struct gpio_chip so that
+ the irqchip can initialize. E.g. .dev and .can_sleep shall be set up
+ properly.
+
It is legal for any IRQ consumer to request an IRQ from any irqchip no matter
if that is a combined GPIO+IRQ driver. The basic premise is that gpio_chip and
irq_chip are orthogonal, and offering their services independent of each
diff --git a/Documentation/hsi.txt b/Documentation/hsi.txt
new file mode 100644
index 000000000000..6ac6cd51852a
--- /dev/null
+++ b/Documentation/hsi.txt
@@ -0,0 +1,75 @@
+HSI - High-speed Synchronous Serial Interface
+
+1. Introduction
+~~~~~~~~~~~~~~~
+
+High Speed Syncronous Interface (HSI) is a fullduplex, low latency protocol,
+that is optimized for die-level interconnect between an Application Processor
+and a Baseband chipset. It has been specified by the MIPI alliance in 2003 and
+implemented by multiple vendors since then.
+
+The HSI interface supports full duplex communication over multiple channels
+(typically 8) and is capable of reaching speeds up to 200 Mbit/s.
+
+The serial protocol uses two signals, DATA and FLAG as combined data and clock
+signals and an additional READY signal for flow control. An additional WAKE
+signal can be used to wakeup the chips from standby modes. The signals are
+commonly prefixed by AC for signals going from the application die to the
+cellular die and CA for signals going the other way around.
+
++------------+ +---------------+
+| Cellular | | Application |
+| Die | | Die |
+| | - - - - - - CAWAKE - - - - - - >| |
+| T|------------ CADATA ------------>|R |
+| X|------------ CAFLAG ------------>|X |
+| |<----------- ACREADY ------------| |
+| | | |
+| | | |
+| |< - - - - - ACWAKE - - - - - - -| |
+| R|<----------- ACDATA -------------|T |
+| X|<----------- ACFLAG -------------|X |
+| |------------ CAREADY ----------->| |
+| | | |
+| | | |
++------------+ +---------------+
+
+2. HSI Subsystem in Linux
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In the Linux kernel the hsi subsystem is supposed to be used for HSI devices.
+The hsi subsystem contains drivers for hsi controllers including support for
+multi-port controllers and provides a generic API for using the HSI ports.
+
+It also contains HSI client drivers, which make use of the generic API to
+implement a protocol used on the HSI interface. These client drivers can
+use an arbitrary number of channels.
+
+3. hsi-char Device
+~~~~~~~~~~~~~~~~~~
+
+Each port automatically registers a generic client driver called hsi_char,
+which provides a charecter device for userspace representing the HSI port.
+It can be used to communicate via HSI from userspace. Userspace may
+configure the hsi_char device using the following ioctl commands:
+
+* HSC_RESET:
+ - flush the HSI port
+
+* HSC_SET_PM
+ - enable or disable the client.
+
+* HSC_SEND_BREAK
+ - send break
+
+* HSC_SET_RX
+ - set RX configuration
+
+* HSC_GET_RX
+ - get RX configuration
+
+* HSC_SET_TX
+ - set TX configuration
+
+* HSC_GET_TX
+ - get TX configuration
diff --git a/Documentation/hwmon/sysfs-interface b/Documentation/hwmon/sysfs-interface
index 79f8257dd790..2cc95ad46604 100644
--- a/Documentation/hwmon/sysfs-interface
+++ b/Documentation/hwmon/sysfs-interface
@@ -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.
diff --git a/Documentation/input/elantech.txt b/Documentation/input/elantech.txt
index 5602eb71ad5d..e1ae127ed099 100644
--- a/Documentation/input/elantech.txt
+++ b/Documentation/input/elantech.txt
@@ -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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/Documentation/ja_JP/HOWTO b/Documentation/ja_JP/HOWTO
index 0091a8215ac1..b61885c35ce1 100644
--- a/Documentation/ja_JP/HOWTO
+++ b/Documentation/ja_JP/HOWTO
@@ -315,7 +315,7 @@ Andrew Morton ㌠Linux-kernel メーリングリストã«ã‚«ãƒ¼ãƒãƒ«ãƒªãƒªãƒ¼ã
ã‚‚ã—ã€3.x.y カーãƒãƒ«ãŒå­˜åœ¨ã—ãªã„å ´åˆã«ã¯ã€ç•ªå·ãŒä¸€ç•ªå¤§ãã„ 3.x ãŒ
最新ã®å®‰å®šç‰ˆã‚«ãƒ¼ãƒãƒ«ã§ã™ã€‚
-3.x.y 㯠"stable" ãƒãƒ¼ãƒ  <stable@kernel.org> ã§ãƒ¡ãƒ³ãƒ†ã•ã‚Œã¦ãŠã‚Šã€å¿…
+3.x.y 㯠"stable" ãƒãƒ¼ãƒ  <stable@vger.kernel.org> ã§ãƒ¡ãƒ³ãƒ†ã•ã‚Œã¦ãŠã‚Šã€å¿…
è¦ã«å¿œã˜ã¦ãƒªãƒªãƒ¼ã‚¹ã•ã‚Œã¾ã™ã€‚通常ã®ãƒªãƒªãƒ¼ã‚¹æœŸé–“㯠2週間毎ã§ã™ãŒã€å·®ã—è¿«ã£
ãŸå•é¡ŒãŒãªã‘ã‚Œã°ã‚‚ã†å°‘ã—é•·ããªã‚‹ã“ã¨ã‚‚ã‚ã‚Šã¾ã™ã€‚セキュリティ関連ã®å•é¡Œ
ã®å ´åˆã¯ã“ã‚Œã«å¯¾ã—ã¦ã ã„ãŸã„ã®å ´åˆã€ã™ãã«ãƒªãƒªãƒ¼ã‚¹ãŒã•ã‚Œã¾ã™ã€‚
diff --git a/Documentation/ja_JP/stable_kernel_rules.txt b/Documentation/ja_JP/stable_kernel_rules.txt
index 14265837c4ce..9dbda9b5d21e 100644
--- a/Documentation/ja_JP/stable_kernel_rules.txt
+++ b/Documentation/ja_JP/stable_kernel_rules.txt
@@ -50,16 +50,16 @@ linux-2.6.29/Documentation/stable_kernel_rules.txt
-stable ツリーã«ãƒ‘ッãƒã‚’é€ä»˜ã™ã‚‹æ‰‹ç¶šã-
- - 上記ã®è¦å‰‡ã«å¾“ã£ã¦ã„ã‚‹ã‹ã‚’確èªã—ãŸå¾Œã«ã€stable@kernel.org ã«ãƒ‘ッãƒ
+ - 上記ã®è¦å‰‡ã«å¾“ã£ã¦ã„ã‚‹ã‹ã‚’確èªã—ãŸå¾Œã«ã€stable@vger.kernel.org ã«ãƒ‘ッãƒ
ã‚’é€ã‚‹ã€‚
- é€ä¿¡è€…ã¯ãƒ‘ッãƒãŒã‚­ãƒ¥ãƒ¼ã«å—ã‘付ã‘られãŸéš›ã«ã¯ ACK ã‚’ã€å´ä¸‹ã•ã‚ŒãŸå ´åˆ
ã«ã¯ NAK ã‚’å—ã‘å–る。ã“ã®åå¿œã¯é–‹ç™ºè€…ãŸã¡ã®ã‚¹ã‚±ã‚¸ãƒ¥ãƒ¼ãƒ«ã«ã‚ˆã£ã¦ã€æ•°
æ—¥ã‹ã‹ã‚‹å ´åˆãŒã‚る。
- ã‚‚ã—å—ã‘å–られãŸã‚‰ã€ãƒ‘ッãƒã¯ä»–ã®é–‹ç™ºè€…ãŸã¡ã¨é–¢é€£ã™ã‚‹ã‚µãƒ–システムã®
メンテナーã«ã‚ˆã‚‹ãƒ¬ãƒ“ューã®ãŸã‚ã« -stable キューã«è¿½åŠ ã•ã‚Œã‚‹ã€‚
- - パッãƒã« stable@kernel.org ã®ã‚¢ãƒ‰ãƒ¬ã‚¹ãŒä»˜åŠ ã•ã‚Œã¦ã„ã‚‹ã¨ãã«ã¯ã€ãã‚Œ
+ - パッãƒã« stable@vger.kernel.org ã®ã‚¢ãƒ‰ãƒ¬ã‚¹ãŒä»˜åŠ ã•ã‚Œã¦ã„ã‚‹ã¨ãã«ã¯ã€ãã‚Œ
㌠Linus ã®ãƒ„リーã«å…¥ã‚‹æ™‚ã«è‡ªå‹•çš„ã« stable ãƒãƒ¼ãƒ ã« email ã•ã‚Œã‚‹ã€‚
- - セキュリティパッãƒã¯ã“ã®ã‚¨ã‚¤ãƒªã‚¢ã‚¹ (stable@kernel.org) ã«é€ã‚‰ã‚Œã‚‹ã¹
+ - セキュリティパッãƒã¯ã“ã®ã‚¨ã‚¤ãƒªã‚¢ã‚¹ (stable@vger.kernel.org) ã«é€ã‚‰ã‚Œã‚‹ã¹
ãã§ã¯ãªãã€ä»£ã‚ã‚Šã« security@kernel.org ã®ã‚¢ãƒ‰ãƒ¬ã‚¹ã«é€ã‚‰ã‚Œã‚‹ã€‚
レビューサイクル-
diff --git a/Documentation/java.txt b/Documentation/java.txt
index e6a723281547..418020584ccc 100644
--- a/Documentation/java.txt
+++ b/Documentation/java.txt
@@ -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:
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 03e50b4883a8..7da289ee0589 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -804,13 +804,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
dhash_entries= [KNL]
Set number of hash buckets for dentry cache.
- digi= [HW,SERIAL]
- IO parameters + enable/disable command.
-
- digiepca= [HW,SERIAL]
- See drivers/char/README.epca and
- Documentation/serial/digiepca.txt.
-
disable= [IPV6]
See Documentation/networking/ipv6.txt.
@@ -899,7 +892,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
(mmio) or 32-bit (mmio32).
The options are the same as for ttyS, above.
- earlyprintk= [X86,SH,BLACKFIN,ARM]
+ earlyprintk= [X86,SH,BLACKFIN,ARM,M68k]
earlyprintk=vga
earlyprintk=efi
earlyprintk=xen
@@ -2225,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.
@@ -2939,9 +2932,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
rhash_entries= [KNL,NET]
Set number of hash buckets for route cache
- riscom8= [HW,SERIAL]
- Format: <io_board1>[,<io_board2>[,...<io_boardN>]]
-
ro [KNL] Mount root device read-only on boot
root= [KNL] Root filesystem
@@ -3083,9 +3073,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
sonypi.*= [HW] Sony Programmable I/O Control Device driver
See Documentation/laptops/sonypi.txt
- specialix= [HW,SERIAL] Specialix multi-serial port adapter
- See Documentation/serial/specialix.txt.
-
spia_io_base= [HW,MTD]
spia_fio_base=
spia_pedr=
diff --git a/Documentation/magic-number.txt b/Documentation/magic-number.txt
index 76d80a64bbe1..4c8e142db2ef 100644
--- a/Documentation/magic-number.txt
+++ b/Documentation/magic-number.txt
@@ -63,8 +63,6 @@ Magic Name Number Structure File
PG_MAGIC 'P' pg_{read,write}_hdr include/linux/pg.h
CMAGIC 0x0111 user include/linux/a.out.h
MKISS_DRIVER_MAGIC 0x04bf mkiss_channel drivers/net/mkiss.h
-RISCOM8_MAGIC 0x0907 riscom_port drivers/char/riscom8.h
-SPECIALIX_MAGIC 0x0907 specialix_port drivers/char/specialix_io8.h
HDLC_MAGIC 0x239e n_hdlc drivers/char/n_hdlc.c
APM_BIOS_MAGIC 0x4101 apm_user arch/x86/kernel/apm_32.c
CYCLADES_MAGIC 0x4359 cyclades_port include/linux/cyclades.h
@@ -82,7 +80,6 @@ STRIP_MAGIC 0x5303 strip drivers/net/strip.c
X25_ASY_MAGIC 0x5303 x25_asy drivers/net/x25_asy.h
SIXPACK_MAGIC 0x5304 sixpack drivers/net/hamradio/6pack.h
AX25_MAGIC 0x5316 ax_disp drivers/net/mkiss.h
-ESP_MAGIC 0x53ee esp_struct drivers/char/esp.h
TTY_MAGIC 0x5401 tty_struct include/linux/tty.h
MGSL_MAGIC 0x5401 mgsl_info drivers/char/synclink.c
TTY_DRIVER_MAGIC 0x5402 tty_driver include/linux/tty_driver.h
@@ -94,13 +91,10 @@ USB_BLUETOOTH_MAGIC 0x6d02 usb_bluetooth drivers/usb/class/bluetty.c
RFCOMM_TTY_MAGIC 0x6d02 net/bluetooth/rfcomm/tty.c
USB_SERIAL_PORT_MAGIC 0x7301 usb_serial_port drivers/usb/serial/usb-serial.h
CG_MAGIC 0x00090255 ufs_cylinder_group include/linux/ufs_fs.h
-A2232_MAGIC 0x000a2232 gs_port drivers/char/ser_a2232.h
RPORT_MAGIC 0x00525001 r_port drivers/char/rocket_int.h
LSEMAGIC 0x05091998 lse drivers/fc4/fc.c
GDTIOCTL_MAGIC 0x06030f07 gdth_iowr_str drivers/scsi/gdth_ioctl.h
RIEBL_MAGIC 0x09051990 drivers/net/atarilance.c
-RIO_MAGIC 0x12345678 gs_port drivers/char/rio/rio_linux.c
-SX_MAGIC 0x12345678 gs_port drivers/char/sx.h
NBD_REQUEST_MAGIC 0x12560953 nbd_request include/linux/nbd.h
RED_MAGIC2 0x170fc2a5 (any) mm/slab.c
BAYCOM_MAGIC 0x19730510 baycom_state drivers/net/baycom_epp.c
@@ -116,7 +110,6 @@ ISDN_ASYNC_MAGIC 0x49344C01 modem_info include/linux/isdn.h
CTC_ASYNC_MAGIC 0x49344C01 ctc_tty_info drivers/s390/net/ctctty.c
ISDN_NET_MAGIC 0x49344C02 isdn_net_local_s drivers/isdn/i4l/isdn_net_lib.h
SAVEKMSG_MAGIC2 0x4B4D5347 savekmsg arch/*/amiga/config.c
-STLI_BOARDMAGIC 0x4bc6c825 stlibrd include/linux/istallion.h
CS_STATE_MAGIC 0x4c4f4749 cs_state sound/oss/cs46xx.c
SLAB_C_MAGIC 0x4f17a36d kmem_cache mm/slab.c
COW_MAGIC 0x4f4f4f4d cow_header_v1 arch/um/drivers/ubd_user.c
@@ -127,10 +120,8 @@ SCC_MAGIC 0x52696368 gs_port drivers/char/scc.h
SAVEKMSG_MAGIC1 0x53415645 savekmsg arch/*/amiga/config.c
GDA_MAGIC 0x58464552 gda arch/mips/include/asm/sn/gda.h
RED_MAGIC1 0x5a2cf071 (any) mm/slab.c
-STL_PORTMAGIC 0x5a7182c9 stlport include/linux/stallion.h
EEPROM_MAGIC_VALUE 0x5ab478d2 lanai_dev drivers/atm/lanai.c
HDLCDRV_MAGIC 0x5ac6e778 hdlcdrv_state include/linux/hdlcdrv.h
-EPCA_MAGIC 0x5c6df104 channel include/linux/epca.h
PCXX_MAGIC 0x5c6df104 channel drivers/char/pcxx.h
KV_MAGIC 0x5f4b565f kernel_vars_s arch/mips/include/asm/sn/klkernvars.h
I810_STATE_MAGIC 0x63657373 i810_state sound/oss/i810_audio.c
@@ -142,17 +133,14 @@ SLOT_MAGIC 0x67267322 slot drivers/hotplug/acpiphp.h
LO_MAGIC 0x68797548 nbd_device include/linux/nbd.h
OPROFILE_MAGIC 0x6f70726f super_block drivers/oprofile/oprofilefs.h
M3_STATE_MAGIC 0x734d724d m3_state sound/oss/maestro3.c
-STL_PANELMAGIC 0x7ef621a1 stlpanel include/linux/stallion.h
VMALLOC_MAGIC 0x87654320 snd_alloc_track sound/core/memory.c
KMALLOC_MAGIC 0x87654321 snd_alloc_track sound/core/memory.c
PWC_MAGIC 0x89DC10AB pwc_device drivers/usb/media/pwc.h
NBD_REPLY_MAGIC 0x96744668 nbd_reply include/linux/nbd.h
-STL_BOARDMAGIC 0xa2267f52 stlbrd include/linux/stallion.h
ENI155_MAGIC 0xa54b872d midway_eprom drivers/atm/eni.h
SCI_MAGIC 0xbabeface gs_port drivers/char/sh-sci.h
CODA_MAGIC 0xC0DAC0DA coda_file_info fs/coda/coda_fs_i.h
DPMEM_MAGIC 0xc0ffee11 gdt_pci_sram drivers/scsi/gdth.h
-STLI_PORTMAGIC 0xe671c7a1 stliport include/linux/istallion.h
YAM_MAGIC 0xF10A7654 yam_port drivers/net/hamradio/yam.c
CCB_MAGIC 0xf2691ad2 ccb drivers/scsi/ncr53c8xx.c
QUEUE_MAGIC_FREE 0xf7e1c9a3 queue_entry drivers/scsi/arm/queue.c
diff --git a/Documentation/networking/filter.txt b/Documentation/networking/filter.txt
index 81f940f4e884..e3ba753cb714 100644
--- a/Documentation/networking/filter.txt
+++ b/Documentation/networking/filter.txt
@@ -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)
diff --git a/Documentation/networking/packet_mmap.txt b/Documentation/networking/packet_mmap.txt
index 6fea79efb4cb..38112d512f47 100644
--- a/Documentation/networking/packet_mmap.txt
+++ b/Documentation/networking/packet_mmap.txt
@@ -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
diff --git a/Documentation/networking/scaling.txt b/Documentation/networking/scaling.txt
index ca6977f5b2ed..99ca40e8e810 100644
--- a/Documentation/networking/scaling.txt
+++ b/Documentation/networking/scaling.txt
@@ -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)
diff --git a/Documentation/serial/00-INDEX b/Documentation/serial/00-INDEX
index f9c6b5ed03e7..8021a9f29fc5 100644
--- a/Documentation/serial/00-INDEX
+++ b/Documentation/serial/00-INDEX
@@ -2,23 +2,15 @@
- this file.
README.cycladesZ
- info on Cyclades-Z firmware loading.
-digiepca.txt
- - info on Digi Intl. {PC,PCI,EISA}Xx and Xem series cards.
driver
- intro to the low level serial driver.
moxa-smartio
- file with info on installing/using Moxa multiport serial driver.
n_gsm.txt
- GSM 0710 tty multiplexer howto.
-riscom8.txt
- - notes on using the RISCom/8 multi-port serial driver.
rocket.txt
- info on the Comtrol RocketPort multiport serial driver.
serial-rs485.txt
- info about RS485 structures and support in the kernel.
-specialix.txt
- - info on hardware/driver for specialix IO8+ multiport serial card.
-sx.txt
- - info on the Specialix SX/SI multiport serial driver.
tty.txt
- guide to the locking policies of the tty layer.
diff --git a/Documentation/serial/digiepca.txt b/Documentation/serial/digiepca.txt
deleted file mode 100644
index f2560e22f2c9..000000000000
--- a/Documentation/serial/digiepca.txt
+++ /dev/null
@@ -1,98 +0,0 @@
-NOTE: This driver is obsolete. Digi provides a 2.6 driver (dgdm) at
-http://www.digi.com for PCI cards. They no longer maintain this driver,
-and have no 2.6 driver for ISA cards.
-
-This driver requires a number of user-space tools. They can be acquired from
-http://www.digi.com, but only works with 2.4 kernels.
-
-
-The Digi Intl. epca driver.
-----------------------------
-The Digi Intl. epca driver for Linux supports the following boards:
-
-Digi PC/Xem, PC/Xr, PC/Xe, PC/Xi, PC/Xeve
-Digi EISA/Xem, PCI/Xem, PCI/Xr
-
-Limitations:
-------------
-Currently the driver only autoprobes for supported PCI boards.
-
-The Linux MAKEDEV command does not support generating the Digiboard
-Devices. Users executing digiConfig to setup EISA and PC series cards
-will have their device nodes automatically constructed (cud?? for ~CLOCAL,
-and ttyD?? for CLOCAL). Users wishing to boot their board from the LILO
-prompt, or those users booting PCI cards may use buildDIGI to construct
-the necessary nodes.
-
-Notes:
-------
-This driver may be configured via LILO. For users who have already configured
-their driver using digiConfig, configuring from LILO will override previous
-settings. Multiple boards may be configured by issuing multiple LILO command
-lines. For examples see the bottom of this document.
-
-Device names start at 0 and continue up. Beware of this as previous Digi
-drivers started device names with 1.
-
-PCI boards are auto-detected and configured by the driver. PCI boards will
-be allocated device numbers (internally) beginning with the lowest PCI slot
-first. In other words a PCI card in slot 3 will always have higher device
-nodes than a PCI card in slot 1.
-
-LILO config examples:
----------------------
-Using LILO's APPEND command, a string of comma separated identifiers or
-integers can be used to configure supported boards. The six values in order
-are:
-
- Enable/Disable this card or Override,
- Type of card: PC/Xe (AccelePort) (0), PC/Xeve (1), PC/Xem or PC/Xr (2),
- EISA/Xem (3), PC/64Xe (4), PC/Xi (5),
- Enable/Disable alternate pin arrangement,
- Number of ports on this card,
- I/O Port where card is configured (in HEX if using string identifiers),
- Base of memory window (in HEX if using string identifiers),
-
-NOTE : PCI boards are auto-detected and configured. Do not attempt to
-configure PCI boards with the LILO append command. If you wish to override
-previous configuration data (As set by digiConfig), but you do not wish to
-configure any specific card (Example if there are PCI cards in the system)
-the following override command will accomplish this:
--> append="digi=2"
-
-Samples:
- append="digiepca=E,PC/Xe,D,16,200,D0000"
- or
- append="digi=1,0,0,16,512,851968"
-
-Supporting Tools:
------------------
-Supporting tools include digiDload, digiConfig, buildPCI, and ditty. See
-drivers/char/README.epca for more details. Note,
-this driver REQUIRES that digiDload be executed prior to it being used.
-Failure to do this will result in an ENODEV error.
-
-Documentation:
---------------
-Complete documentation for this product may be found in the tool package.
-
-Sources of information and support:
------------------------------------
-Digi Intl. support site for this product:
-
--> http://www.digi.com
-
-Acknowledgments:
-----------------
-Much of this work (And even text) was derived from a similar document
-supporting the original public domain DigiBoard driver Copyright (C)
-1994,1995 Troy De Jongh. Many thanks to Christoph Lameter
-(christoph@lameter.com) and Mike McLagan (mike.mclagan@linux.org) who authored
-and contributed to the original document.
-
-Changelog:
-----------
-10-29-04: Update status of driver, remove dead links in document
- James Nelson <james4765@gmail.com>
-
-2000 (?) Original Document
diff --git a/Documentation/serial/riscom8.txt b/Documentation/serial/riscom8.txt
deleted file mode 100644
index 14f61fdad7ca..000000000000
--- a/Documentation/serial/riscom8.txt
+++ /dev/null
@@ -1,36 +0,0 @@
-* NOTE - this is an unmaintained driver. The original author cannot be located.
-
-SDL Communications is now SBS Technologies, and does not have any
-information on these ancient ISA cards on their website.
-
-James Nelson <james4765@gmail.com> - 12-12-2004
-
- This is the README for RISCom/8 multi-port serial driver
- (C) 1994-1996 D.Gorodchanin
- See file LICENSE for terms and conditions.
-
-NOTE: English is not my native language.
- I'm sorry for any mistakes in this text.
-
-Misc. notes for RISCom/8 serial driver, in no particular order :)
-
-1) This driver can support up to 4 boards at time.
- Use string "riscom8=0xXXX,0xXXX,0xXXX,0xXXX" at LILO prompt, for
- setting I/O base addresses for boards. If you compile driver
- as module use modprobe options "iobase=0xXXX iobase1=0xXXX iobase2=..."
-
-2) The driver partially supports famous 'setserial' program, you can use almost
- any of its options, excluding port & irq settings.
-
-3) There are some misc. defines at the beginning of riscom8.c, please read the
- comments and try to change some of them in case of problems.
-
-4) I consider the current state of the driver as BETA.
-
-5) SDL Communications WWW page is http://www.sdlcomm.com.
-
-6) You can use the MAKEDEV program to create RISCom/8 /dev/ttyL* entries.
-
-7) Minor numbers for first board are 0-7, for second 8-15, etc.
-
-22 Apr 1996.
diff --git a/Documentation/serial/specialix.txt b/Documentation/serial/specialix.txt
deleted file mode 100644
index 6eb6f3a3331c..000000000000
--- a/Documentation/serial/specialix.txt
+++ /dev/null
@@ -1,383 +0,0 @@
-
- specialix.txt -- specialix IO8+ multiport serial driver readme.
-
-
-
- Copyright (C) 1997 Roger Wolff (R.E.Wolff@BitWizard.nl)
-
- Specialix pays for the development and support of this driver.
- Please DO contact io8-linux@specialix.co.uk if you require
- support.
-
- This driver was developed in the BitWizard linux device
- driver service. If you require a linux device driver for your
- product, please contact devices@BitWizard.nl for a quote.
-
- This code is firmly based on the riscom/8 serial driver,
- written by Dmitry Gorodchanin. The specialix IO8+ card
- programming information was obtained from the CL-CD1865 Data
- Book, and Specialix document number 6200059: IO8+ Hardware
- Functional Specification, augmented by document number 6200088:
- Merak Hardware Functional Specification. (IO8+/PCI is also
- called Merak)
-
-
- 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., 675 Mass Ave, Cambridge, MA 02139,
- USA.
-
-
-Intro
-=====
-
-
-This file contains some random information, that I like to have online
-instead of in a manual that can get lost. Ever misplace your Linux
-kernel sources? And the manual of one of the boards in your computer?
-
-
-Addresses and interrupts
-========================
-
-Address dip switch settings:
-The dip switch sets bits 2-9 of the IO address.
-
- 9 8 7 6 5 4 3 2
- +-----------------+
- 0 | X X X X X X X |
- | | = IoBase = 0x100
- 1 | X |
- +-----------------+ ------ RS232 connectors ---->
-
- | | |
- edge connector
- | | |
- V V V
-
-Base address 0x100 caused a conflict in one of my computers once. I
-haven't the foggiest why. My Specialix card is now at 0x180. My
-other computer runs just fine with the Specialix card at 0x100....
-The card occupies 4 addresses, but actually only two are really used.
-
-The PCI version doesn't have any dip switches. The BIOS assigns
-an IO address.
-
-The driver now still autoprobes at 0x100, 0x180, 0x250 and 0x260. If
-that causes trouble for you, please report that. I'll remove
-autoprobing then.
-
-The driver will tell the card what IRQ to use, so you don't have to
-change any jumpers to change the IRQ. Just use a command line
-argument (irq=xx) to the insmod program to set the interrupt.
-
-The BIOS assigns the IRQ on the PCI version. You have no say in what
-IRQ to use in that case.
-
-If your specialix cards are not at the default locations, you can use
-the kernel command line argument "specialix=io0,irq0,io1,irq1...".
-Here "io0" is the io address for the first card, and "irq0" is the
-irq line that the first card should use. And so on.
-
-Examples.
-
-You use the driver as a module and have three cards at 0x100, 0x250
-and 0x180. And some way or another you want them detected in that
-order. Moreover irq 12 is taken (e.g. by your PS/2 mouse).
-
- insmod specialix.o iobase=0x100,0x250,0x180 irq=9,11,15
-
-The same three cards, but now in the kernel would require you to
-add
-
- specialix=0x100,9,0x250,11,0x180,15
-
-to the command line. This would become
-
- append="specialix=0x100,9,0x250,11,0x180,15"
-
-in your /etc/lilo.conf file if you use lilo.
-
-The Specialix driver is slightly odd: It allows you to have the second
-or third card detected without having a first card. This has
-advantages and disadvantages. A slot that isn't filled by an ISA card,
-might be filled if a PCI card is detected. Thus if you have an ISA
-card at 0x250 and a PCI card, you would get:
-
-sx0: specialix IO8+ Board at 0x100 not found.
-sx1: specialix IO8+ Board at 0x180 not found.
-sx2: specialix IO8+ board detected at 0x250, IRQ 12, CD1865 Rev. B.
-sx3: specialix IO8+ Board at 0x260 not found.
-sx0: specialix IO8+ board detected at 0xd800, IRQ 9, CD1865 Rev. B.
-
-This would happen if you don't give any probe hints to the driver.
-If you would specify:
-
- specialix=0x250,11
-
-you'd get the following messages:
-
-sx0: specialix IO8+ board detected at 0x250, IRQ 11, CD1865 Rev. B.
-sx1: specialix IO8+ board detected at 0xd800, IRQ 9, CD1865 Rev. B.
-
-ISA probing is aborted after the IO address you gave is exhausted, and
-the PCI card is now detected as the second card. The ISA card is now
-also forced to IRQ11....
-
-
-Baud rates
-==========
-
-The rev 1.2 and below boards use a CL-CD1864. These chips can only
-do 64kbit. The rev 1.3 and newer boards use a CL-CD1865. These chips
-are officially capable of 115k2.
-
-The Specialix card uses a 25MHz crystal (in times two mode, which in
-fact is a divided by two mode). This is not enough to reach the rated
-115k2 on all ports at the same time. With this clock rate you can only
-do 37% of this rate. This means that at 115k2 on all ports you are
-going to lose characters (The chip cannot handle that many incoming
-bits at this clock rate.) (Yes, you read that correctly: there is a
-limit to the number of -=bits=- per second that the chip can handle.)
-
-If you near the "limit" you will first start to see a graceful
-degradation in that the chip cannot keep the transmitter busy at all
-times. However with a central clock this slow, you can also get it to
-miss incoming characters. The driver will print a warning message when
-you are outside the official specs. The messages usually show up in
-the file /var/log/messages .
-
-The specialix card cannot reliably do 115k2. If you use it, you have
-to do "extensive testing" (*) to verify if it actually works.
-
-When "mgetty" communicates with my modem at 115k2 it reports:
-got: +++[0d]ATQ0V1H0[0d][0d][8a]O[cb][0d][8a]
- ^^^^ ^^^^ ^^^^
-
-The three characters that have the "^^^" under them have suffered a
-bit error in the highest bit. In conclusion: I've tested it, and found
-that it simply DOESN'T work for me. I also suspect that this is also
-caused by the baud rate being just a little bit out of tune.
-
-I upgraded the crystal to 66Mhz on one of my Specialix cards. Works
-great! Contact me for details. (Voids warranty, requires a steady hand
-and more such restrictions....)
-
-
-(*) Cirrus logic CD1864 databook, page 40.
-
-
-Cables for the Specialix IO8+
-=============================
-
-The pinout of the connectors on the IO8+ is:
-
- pin short direction long name
- name
- Pin 1 DCD input Data Carrier Detect
- Pin 2 RXD input Receive
- Pin 3 DTR/RTS output Data Terminal Ready/Ready To Send
- Pin 4 GND - Ground
- Pin 5 TXD output Transmit
- Pin 6 CTS input Clear To Send
-
-
- -- 6 5 4 3 2 1 --
- | |
- | |
- | |
- | |
- +----- -----+
- |__________|
- clip
-
- Front view of an RJ12 connector. Cable moves "into" the paper.
- (the plug is ready to plug into your mouth this way...)
-
-
- NULL cable. I don't know who is going to use these except for
- testing purposes, but I tested the cards with this cable. (It
- took quite a while to figure out, so I'm not going to delete
- it. So there! :-)
-
-
- This end goes This end needs
- straight into the some twists in
- RJ12 plug. the wiring.
- IO8+ RJ12 IO8+ RJ12
- 1 DCD white -
- - - 1 DCD
- 2 RXD black 5 TXD
- 3 DTR/RTS red 6 CTS
- 4 GND green 4 GND
- 5 TXD yellow 2 RXD
- 6 CTS blue 3 DTR/RTS
-
-
- Same NULL cable, but now sorted on the second column.
-
- 1 DCD white -
- - - 1 DCD
- 5 TXD yellow 2 RXD
- 6 CTS blue 3 DTR/RTS
- 4 GND green 4 GND
- 2 RXD black 5 TXD
- 3 DTR/RTS red 6 CTS
-
-
-
- This is a modem cable usable for hardware handshaking:
- RJ12 DB25 DB9
- 1 DCD white 8 DCD 1 DCD
- 2 RXD black 3 RXD 2 RXD
- 3 DTR/RTS red 4 RTS 7 RTS
- 4 GND green 7 GND 5 GND
- 5 TXD yellow 2 TXD 3 TXD
- 6 CTS blue 5 CTS 8 CTS
- +---- 6 DSR 6 DSR
- +---- 20 DTR 4 DTR
-
- This is a modem cable usable for software handshaking:
- It allows you to reset the modem using the DTR ioctls.
- I (REW) have never tested this, "but xxxxxxxxxxxxx
- says that it works." If you test this, please
- tell me and I'll fill in your name on the xxx's.
-
- RJ12 DB25 DB9
- 1 DCD white 8 DCD 1 DCD
- 2 RXD black 3 RXD 2 RXD
- 3 DTR/RTS red 20 DTR 4 DTR
- 4 GND green 7 GND 5 GND
- 5 TXD yellow 2 TXD 3 TXD
- 6 CTS blue 5 CTS 8 CTS
- +---- 6 DSR 6 DSR
- +---- 4 RTS 7 RTS
-
- I bought a 6 wire flat cable. It was colored as indicated.
- Check that yours is the same before you trust me on this.
-
-
-Hardware handshaking issues.
-============================
-
-The driver can be told to operate in two different ways. The default
-behaviour is specialix.sx_rtscts = 0 where the pin behaves as DTR when
-hardware handshaking is off. It behaves as the RTS hardware
-handshaking signal when hardware handshaking is selected.
-
-When you use this, you have to use the appropriate cable. The
-cable will either be compatible with hardware handshaking or with
-software handshaking. So switching on the fly is not really an
-option.
-
-I actually prefer to use the "specialix.sx_rtscts=1" option.
-This makes the DTR/RTS pin always an RTS pin, and ioctls to
-change DTR are always ignored. I have a cable that is configured
-for this.
-
-
-Ports and devices
-=================
-
-Port 0 is the one furthest from the card-edge connector.
-
-Devices:
-
-You should make the devices as follows:
-
-bash
-cd /dev
-for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 \
- 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
-do
- echo -n "$i "
- mknod /dev/ttyW$i c 75 $i
- mknod /dev/cuw$i c 76 $i
-done
-echo ""
-
-If your system doesn't come with these devices preinstalled, bug your
-linux-vendor about this. They have had ample time to get this
-implemented by now.
-
-You cannot have more than 4 boards in one computer. The card only
-supports 4 different interrupts. If you really want this, contact me
-about this and I'll give you a few tips (requires soldering iron)....
-
-If you have enough PCI slots, you can probably use more than 4 PCI
-versions of the card though....
-
-The PCI version of the card cannot adhere to the mechanical part of
-the PCI spec because the 8 serial connectors are simply too large. If
-it doesn't fit in your computer, bring back the card.
-
-
-------------------------------------------------------------------------
-
-
- Fixed bugs and restrictions:
- - During initialization, interrupts are blindly turned on.
- Having a shadow variable would cause an extra memory
- access on every IO instruction.
- - The interrupt (on the card) should be disabled when we
- don't allocate the Linux end of the interrupt. This allows
- a different driver/card to use it while all ports are not in
- use..... (a la standard serial port)
- == An extra _off variant of the sx_in and sx_out macros are
- now available. They don't set the interrupt enable bit.
- These are used during initialization. Normal operation uses
- the old variant which enables the interrupt line.
- - RTS/DTR issue needs to be implemented according to
- specialix' spec.
- I kind of like the "determinism" of the current
- implementation. Compile time flag?
- == Ok. Compile time flag! Default is how Specialix likes it.
- == Now a config time flag! Gets saved in your config file. Neat!
- - Can you set the IO address from the lilo command line?
- If you need this, bug me about it, I'll make it.
- == Hah! No bugging needed. Fixed! :-)
- - Cirrus logic hasn't gotten back to me yet why the CD1865 can
- and the CD1864 can't do 115k2. I suspect that this is
- because the CD1864 is not rated for 33MHz operation.
- Therefore the CD1864 versions of the card can't do 115k2 on
- all ports just like the CD1865 versions. The driver does
- not block 115k2 on CD1864 cards.
- == I called the Cirrus Logic representative here in Holland.
- The CD1864 databook is identical to the CD1865 databook,
- except for an extra warning at the end. Similar Bit errors
- have been observed in testing at 115k2 on both an 1865 and
- a 1864 chip. I see no reason why I would prohibit 115k2 on
- 1864 chips and not do it on 1865 chips. Actually there is
- reason to prohibit it on BOTH chips. I print a warning.
- If you use 115k2, you're on your own.
- - A spiky CD may send spurious HUPs. Also in CLOCAL???
- -- A fix for this turned out to be counter productive.
- Different fix? Current behaviour is acceptable?
- -- Maybe the current implementation is correct. If anybody
- gets bitten by this, please report, and it will get fixed.
-
- -- Testing revealed that when in CLOCAL, the problem doesn't
- occur. As warned for in the CD1865 manual, the chip may
- send modem intr's on a spike. We could filter those out,
- but that would be a cludge anyway (You'd still risk getting
- a spurious HUP when two spikes occur.).....
-
-
-
- Bugs & restrictions:
- - This is a difficult card to autoprobe.
- You have to WRITE to the address register to even
- read-probe a CD186x register. Disable autodetection?
- -- Specialix: any suggestions?
-
-
diff --git a/Documentation/serial/sx.txt b/Documentation/serial/sx.txt
deleted file mode 100644
index cb4efa0fb5cc..000000000000
--- a/Documentation/serial/sx.txt
+++ /dev/null
@@ -1,294 +0,0 @@
-
- sx.txt -- specialix SX/SI multiport serial driver readme.
-
-
-
- Copyright (C) 1997 Roger Wolff (R.E.Wolff@BitWizard.nl)
-
- Specialix pays for the development and support of this driver.
- Please DO contact support@specialix.co.uk if you require
- support.
-
- This driver was developed in the BitWizard linux device
- driver service. If you require a linux device driver for your
- product, please contact devices@BitWizard.nl for a quote.
-
- (History)
- There used to be an SI driver by Simon Allan. This is a complete
- rewrite from scratch. Just a few lines-of-code have been snatched.
-
- (Sources)
- Specialix document number 6210028: SX Host Card and Download Code
- Software Functional Specification.
-
- (Copying)
- 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., 675 Mass Ave, Cambridge, MA 02139,
- USA.
-
- (Addendum)
- I'd appreciate it that if you have fixes, that you send them
- to me first.
-
-
-Introduction
-============
-
-This file contains some random information, that I like to have online
-instead of in a manual that can get lost. Ever misplace your Linux
-kernel sources? And the manual of one of the boards in your computer?
-
-
-Theory of operation
-===================
-
-An important thing to know is that the driver itself doesn't have the
-firmware for the card. This means that you need the separate package
-"sx_firmware". For now you can get the source at
-
- ftp://ftp.bitwizard.nl/specialix/sx_firmware_<version>.tgz
-
-The firmware load needs a "misc" device, so you'll need to enable the
-"Support for user misc device modules" in your kernel configuration.
-The misc device needs to be called "/dev/specialix_sxctl". It needs
-misc major 10, and minor number 167 (assigned by HPA). The section
-on creating device files below also creates this device.
-
-After loading the sx.o module into your kernel, the driver will report
-the number of cards detected, but because it doesn't have any
-firmware, it will not be able to determine the number of ports. Only
-when you then run "sx_firmware" will the firmware be downloaded and
-the rest of the driver initialized. At that time the sx_firmware
-program will report the number of ports installed.
-
-In contrast with many other multi port serial cards, some of the data
-structures are only allocated when the card knows the number of ports
-that are connected. This means we won't waste memory for 120 port
-descriptor structures when you only have 8 ports. If you experience
-problems due to this, please report them: I haven't seen any.
-
-
-Interrupts
-==========
-
-A multi port serial card, would generate a horrendous amount of
-interrupts if it would interrupt the CPU for every received
-character. Even more than 10 years ago, the trick not to use
-interrupts but to poll the serial cards was invented.
-
-The SX card allow us to do this two ways. First the card limits its
-own interrupt rate to a rate that won't overwhelm the CPU. Secondly,
-we could forget about the cards interrupt completely and use the
-internal timer for this purpose.
-
-Polling the card can take up to a few percent of your CPU. Using the
-interrupts would be better if you have most of the ports idle. Using
-timer-based polling is better if your card almost always has work to
-do. You save the separate interrupt in that case.
-
-In any case, it doesn't really matter all that much.
-
-The most common problem with interrupts is that for ISA cards in a PCI
-system the BIOS has to be told to configure that interrupt as "legacy
-ISA". Otherwise the card can pull on the interrupt line all it wants
-but the CPU won't see this.
-
-If you can't get the interrupt to work, remember that polling mode is
-more efficient (provided you actually use the card intensively).
-
-
-Allowed Configurations
-======================
-
-Some configurations are disallowed. Even though at a glance they might
-seem to work, they are known to lockup the bus between the host card
-and the device concentrators. You should respect the drivers decision
-not to support certain configurations. It's there for a reason.
-
-Warning: Seriously technical stuff ahead. Executive summary: Don't use
-SX cards except configured at a 64k boundary. Skip the next paragraph.
-
-The SX cards can theoretically be placed at a 32k boundary. So for
-instance you can put an SX card at 0xc8000-0xd7fff. This is not a
-"recommended configuration". ISA cards have to tell the bus controller
-how they like their timing. Due to timing issues they have to do this
-based on which 64k window the address falls into. This means that the
-32k window below and above the SX card have to use exactly the same
-timing as the SX card. That reportedly works for other SX cards. But
-you're still left with two useless 32k windows that should not be used
-by anybody else.
-
-
-Configuring the driver
-======================
-
-PCI cards are always detected. The driver auto-probes for ISA cards at
-some sensible addresses. Please report if the auto-probe causes trouble
-in your system, or when a card isn't detected.
-
-I'm afraid I haven't implemented "kernel command line parameters" yet.
-This means that if the default doesn't work for you, you shouldn't use
-the compiled-into-the-kernel version of the driver. Use a module
-instead. If you convince me that you need this, I'll make it for
-you. Deal?
-
-I'm afraid that the module parameters are a bit clumsy. If you have a
-better idea, please tell me.
-
-You can specify several parameters:
-
- sx_poll: number of jiffies between timer-based polls.
-
- Set this to "0" to disable timer based polls.
- Initialization of cards without a working interrupt
- will fail.
-
- Set this to "1" if you want a polling driver.
- (on Intel: 100 polls per second). If you don't use
- fast baud rates, you might consider a value like "5".
- (If you don't know how to do the math, use 1).
-
- sx_slowpoll: Number of jiffies between timer-based polls.
- Set this to "100" to poll once a second.
- This should get the card out of a stall if the driver
- ever misses an interrupt. I've never seen this happen,
- and if it does, that's a bug. Tell me.
-
- sx_maxints: Number of interrupts to request from the card.
- The card normally limits interrupts to about 100 per
- second to offload the host CPU. You can increase this
- number to reduce latency on the card a little.
- Note that if you give a very high number you can overload
- your CPU as well as the CPU on the host card. This setting
- is inaccurate and not recommended for SI cards (But it
- works).
-
- sx_irqmask: The mask of allowable IRQs to use. I suggest you set
- this to 0 (disable IRQs all together) and use polling if
- the assignment of IRQs becomes problematic. This is defined
- as the sum of (1 << irq) 's that you want to allow. So
- sx_irqmask of 8 (1 << 3) specifies that only irq 3 may
- be used by the SX driver. If you want to specify to the
- driver: "Either irq 11 or 12 is ok for you to use", then
- specify (1 << 11) | (1 << 12) = 0x1800 .
-
- sx_debug: You can enable different sorts of debug traces with this.
- At "-1" all debugging traces are active. You'll get several
- times more debugging output than you'll get characters
- transmitted.
-
-
-Baud rates
-==========
-
-Theoretically new SXDCs should be capable of more than 460k
-baud. However the line drivers usually give up before that. Also the
-CPU on the card may not be able to handle 8 channels going at full
-blast at that speed. Moreover, the buffers are not large enough to
-allow operation with 100 interrupts per second. You'll have to realize
-that the card has a 256 byte buffer, so you'll have to increase the
-number of interrupts per second if you have more than 256*100 bytes
-per second to transmit. If you do any performance testing in this
-area, I'd be glad to hear from you...
-
-(Psst Linux users..... I think the Linux driver is more efficient than
-the driver for other OSes. If you can and want to benchmark them
-against each other, be my guest, and report your findings...... :-)
-
-
-Ports and devices
-=================
-
-Port 0 is the top connector on the module closest to the host
-card. Oh, the ports on the SXDCs and TAs are labelled from 1 to 8
-instead of from 0 to 7, as they are numbered by linux. I'm stubborn in
-this: I know for sure that I wouldn't be able to calculate which port
-is which anymore if I would change that....
-
-
-Devices:
-
-You should make the device files as follows:
-
-#!/bin/sh
-# (I recommend that you cut-and-paste this into a file and run that)
-cd /dev
-t=0
-mknod specialix_sxctl c 10 167
-while [ $t -lt 64 ]
- do
- echo -n "$t "
- mknod ttyX$t c 32 $t
- mknod cux$t c 33 $t
- t=`expr $t + 1`
-done
-echo ""
-rm /etc/psdevtab
-ps > /dev/null
-
-
-This creates 64 devices. If you have more, increase the constant on
-the line with "while". The devices start at 0, as is customary on
-Linux. Specialix seems to like starting the numbering at 1.
-
-If your system doesn't come with these devices pre-installed, bug your
-linux-vendor about this. They should have these devices
-"pre-installed" before the new millennium. The "ps" stuff at the end
-is to "tell" ps that the new devices exist.
-
-Officially the maximum number of cards per computer is 4. This driver
-however supports as many cards in one machine as you want. You'll run
-out of interrupts after a few, but you can switch to polled operation
-then. At about 256 ports (More than 8 cards), we run out of minor
-device numbers. Sorry. I suggest you buy a second computer.... (Or
-switch to RIO).
-
-------------------------------------------------------------------------
-
-
- Fixed bugs and restrictions:
- - Hangup processing.
- -- Done.
-
- - the write path in generic_serial (lockup / oops).
- -- Done (Ugly: not the way I want it. Copied from serial.c).
-
- - write buffer isn't flushed at close.
- -- Done. I still seem to lose a few chars at close.
- Sorry. I think that this is a firmware issue. (-> Specialix)
-
- - drain hardware before changing termios
- - Change debug on the fly.
- - ISA free irq -1. (no firmware loaded).
- - adding c8000 as a probe address. Added warning.
- - Add a RAMtest for the RAM on the card.c
- - Crash when opening a port "way" of the number of allowed ports.
- (for example opening port 60 when there are only 24 ports attached)
- - Sometimes the use-count strays a bit. After a few hours of
- testing the use count is sometimes "3". If you are not like
- me and can remember what you did to get it that way, I'd
- appreciate an Email. Possibly fixed. Tell me if anyone still
- sees this.
- - TAs don't work right if you don't connect all the modem control
- signals. SXDCs do. T225 firmware problem -> Specialix.
- (Mostly fixed now, I think. Tell me if you encounter this!)
-
- Bugs & restrictions:
-
- - Arbitrary baud rates. Requires firmware update. (-> Specialix)
-
- - Low latency (mostly firmware, -> Specialix)
-
-
-
diff --git a/Documentation/stable_kernel_rules.txt b/Documentation/stable_kernel_rules.txt
index b0714d8f678a..cbc2f03056bd 100644
--- a/Documentation/stable_kernel_rules.txt
+++ b/Documentation/stable_kernel_rules.txt
@@ -39,7 +39,7 @@ Procedure for submitting patches to the -stable tree:
the stable tree without anything else needing to be done by the author
or subsystem maintainer.
- If the patch requires other patches as prerequisites which can be
- cherry-picked than this can be specified in the following format in
+ cherry-picked, then this can be specified in the following format in
the sign-off area:
Cc: <stable@vger.kernel.org> # 3.3.x: a1f84a3: sched: Check for idle
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index a9380ba54c8e..b4f53653c106 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -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
diff --git a/Documentation/vm/numa_memory_policy.txt b/Documentation/vm/numa_memory_policy.txt
index 4e7da6543424..badb0507608f 100644
--- a/Documentation/vm/numa_memory_policy.txt
+++ b/Documentation/vm/numa_memory_policy.txt
@@ -174,7 +174,6 @@ Components of Memory Policies
allocation fails, the kernel will search other nodes, in order of
increasing distance from the preferred node based on information
provided by the platform firmware.
- containing the cpu where the allocation takes place.
Internally, the Preferred policy uses a single node--the
preferred_node member of struct mempolicy. When the internal
@@ -275,9 +274,9 @@ Components of Memory Policies
For example, consider a task that is attached to a cpuset with
mems 2-5 that sets an Interleave policy over the same set with
MPOL_F_RELATIVE_NODES. If the cpuset's mems change to 3-7, the
- interleave now occurs over nodes 3,5-6. If the cpuset's mems
+ interleave now occurs over nodes 3,5-7. If the cpuset's mems
then change to 0,2-3,5, then the interleave occurs over nodes
- 0,3,5.
+ 0,2-3,5.
Thanks to the consistent remapping, applications preparing
nodemasks to specify memory policies using this flag should
diff --git a/Documentation/zh_CN/HOWTO b/Documentation/zh_CN/HOWTO
index 6c914aa87e71..54ea24ff63c7 100644
--- a/Documentation/zh_CN/HOWTO
+++ b/Documentation/zh_CN/HOWTO
@@ -237,7 +237,7 @@ kernel.org网站的pub/linux/kernel/v2.6/目录下找到它。它的开å‘éµå¾ª
如果没有2.6.x.y版本内核存在,那么最新的2.6.x版本内核就相当于是当å‰çš„稳定
版内核。
-2.6.x.y版本由“稳定版â€å°ç»„(邮件地å€<stable@kernel.org>)维护,一般隔周å‘
+2.6.x.y版本由“稳定版â€å°ç»„(邮件地å€<stable@vger.kernel.org>)维护,一般隔周å‘
布新版本。
内核æºç ä¸­çš„Documentation/stable_kernel_rules.txt文件具体æ述了å¯è¢«ç¨³å®š
diff --git a/Documentation/zh_CN/io_ordering.txt b/Documentation/zh_CN/io_ordering.txt
new file mode 100644
index 000000000000..e592daf4e014
--- /dev/null
+++ b/Documentation/zh_CN/io_ordering.txt
@@ -0,0 +1,67 @@
+Chinese translated version of Documentation/io_orderings.txt
+
+If you have any comment or update to the content, please contact the
+original document maintainer directly. However, if you have a problem
+communicating in English you can also ask the Chinese maintainer for
+help. Contact the Chinese maintainer if this translation is outdated
+or if there is a problem with the translation.
+
+Chinese maintainer: Lin Yongting <linyongting@gmail.com>
+---------------------------------------------------------------------
+Documentation/io_ordering.txt 的中文翻译
+
+如果想评论或更新本文的内容,请直接è”系原文档的维护者。如果你使用英文
+交æµæœ‰å›°éš¾çš„è¯ï¼Œä¹Ÿå¯ä»¥å‘中文版维护者求助。如果本翻译更新ä¸åŠæ—¶æˆ–者翻
+译存在问题,请è”系中文版维护者。
+
+中文版维护者: æž—æ°¸å¬ Lin Yongting <linyongting@gmail.com>
+中文版翻译者: æž—æ°¸å¬ Lin Yongting <linyongting@gmail.com>
+中文版校译者: æž—æ°¸å¬ Lin Yongting <linyongting@gmail.com>
+
+
+以下为正文
+---------------------------------------------------------------------
+
+在æŸäº›å¹³å°ä¸Šï¼Œæ‰€è°“的内存映射I/O是弱顺åºã€‚在这些平å°ä¸Šï¼Œé©±åŠ¨å¼€å‘者有责任
+ä¿è¯I/O内存映射地å€çš„写æ“作按程åºå›¾æ„的顺åºè¾¾åˆ°è®¾å¤‡ã€‚通常读å–一个“安全â€
+设备寄存器或桥寄存器,触å‘IO芯片清刷未处ç†çš„写æ“作到达设备åŽæ‰å¤„ç†è¯»æ“作,
+而达到ä¿è¯ç›®çš„。驱动程åºé€šå¸¸åœ¨spinlockä¿æŠ¤çš„临界区退出之å‰ä½¿ç”¨è¿™ç§æŠ€æœ¯ã€‚
+这也å¯ä»¥ä¿è¯åŽé¢çš„写æ“作åªåœ¨å‰é¢çš„写æ“作之åŽåˆ°è¾¾è®¾å¤‡ï¼ˆè¿™éžå¸¸ç±»ä¼¼äºŽå†…å­˜
+å±éšœæ“作,mb(),ä¸è¿‡ä»…适用于I/O)。
+
+å‡è®¾ä¸€ä¸ªè®¾å¤‡é©±åŠ¨ç¨‹çš„具体例å­ï¼š
+
+ ...
+CPU A: spin_lock_irqsave(&dev_lock, flags)
+CPU A: val = readl(my_status);
+CPU A: ...
+CPU A: writel(newval, ring_ptr);
+CPU A: spin_unlock_irqrestore(&dev_lock, flags)
+ ...
+CPU B: spin_lock_irqsave(&dev_lock, flags)
+CPU B: val = readl(my_status);
+CPU B: ...
+CPU B: writel(newval2, ring_ptr);
+CPU B: spin_unlock_irqrestore(&dev_lock, flags)
+ ...
+
+上述例å­ä¸­ï¼Œè®¾å¤‡å¯èƒ½ä¼šå…ˆæŽ¥æ”¶åˆ°newval2的值,然åŽæŽ¥æ”¶åˆ°newval的值,问题就
+å‘生了。ä¸è¿‡å¾ˆå®¹æ˜“通过下é¢æ–¹æ³•æ¥ä¿®å¤ï¼š
+
+ ...
+CPU A: spin_lock_irqsave(&dev_lock, flags)
+CPU A: val = readl(my_status);
+CPU A: ...
+CPU A: writel(newval, ring_ptr);
+CPU A: (void)readl(safe_register); /* é…置寄存器?*/
+CPU A: spin_unlock_irqrestore(&dev_lock, flags)
+ ...
+CPU B: spin_lock_irqsave(&dev_lock, flags)
+CPU B: val = readl(my_status);
+CPU B: ...
+CPU B: writel(newval2, ring_ptr);
+CPU B: (void)readl(safe_register); /* é…置寄存器?*/
+CPU B: spin_unlock_irqrestore(&dev_lock, flags)
+
+在解决方案中,读å–safe_register寄存器,触å‘IO芯片清刷未处ç†çš„写æ“作,
+å†å¤„ç†åŽé¢çš„读æ“作,防止引å‘æ•°æ®ä¸ä¸€è‡´é—®é¢˜ã€‚
diff --git a/Documentation/zh_CN/magic-number.txt b/Documentation/zh_CN/magic-number.txt
index 2ebe539f5450..dfb72a5c63e9 100644
--- a/Documentation/zh_CN/magic-number.txt
+++ b/Documentation/zh_CN/magic-number.txt
@@ -63,8 +63,6 @@ struct tty_ldisc {
PG_MAGIC 'P' pg_{read,write}_hdr include/linux/pg.h
CMAGIC 0x0111 user include/linux/a.out.h
MKISS_DRIVER_MAGIC 0x04bf mkiss_channel drivers/net/mkiss.h
-RISCOM8_MAGIC 0x0907 riscom_port drivers/char/riscom8.h
-SPECIALIX_MAGIC 0x0907 specialix_port drivers/char/specialix_io8.h
HDLC_MAGIC 0x239e n_hdlc drivers/char/n_hdlc.c
APM_BIOS_MAGIC 0x4101 apm_user arch/x86/kernel/apm_32.c
CYCLADES_MAGIC 0x4359 cyclades_port include/linux/cyclades.h
@@ -82,7 +80,6 @@ STRIP_MAGIC 0x5303 strip drivers/net/strip.c
X25_ASY_MAGIC 0x5303 x25_asy drivers/net/x25_asy.h
SIXPACK_MAGIC 0x5304 sixpack drivers/net/hamradio/6pack.h
AX25_MAGIC 0x5316 ax_disp drivers/net/mkiss.h
-ESP_MAGIC 0x53ee esp_struct drivers/char/esp.h
TTY_MAGIC 0x5401 tty_struct include/linux/tty.h
MGSL_MAGIC 0x5401 mgsl_info drivers/char/synclink.c
TTY_DRIVER_MAGIC 0x5402 tty_driver include/linux/tty_driver.h
@@ -94,13 +91,10 @@ USB_BLUETOOTH_MAGIC 0x6d02 usb_bluetooth drivers/usb/class/bluetty.c
RFCOMM_TTY_MAGIC 0x6d02 net/bluetooth/rfcomm/tty.c
USB_SERIAL_PORT_MAGIC 0x7301 usb_serial_port drivers/usb/serial/usb-serial.h
CG_MAGIC 0x00090255 ufs_cylinder_group include/linux/ufs_fs.h
-A2232_MAGIC 0x000a2232 gs_port drivers/char/ser_a2232.h
RPORT_MAGIC 0x00525001 r_port drivers/char/rocket_int.h
LSEMAGIC 0x05091998 lse drivers/fc4/fc.c
GDTIOCTL_MAGIC 0x06030f07 gdth_iowr_str drivers/scsi/gdth_ioctl.h
RIEBL_MAGIC 0x09051990 drivers/net/atarilance.c
-RIO_MAGIC 0x12345678 gs_port drivers/char/rio/rio_linux.c
-SX_MAGIC 0x12345678 gs_port drivers/char/sx.h
NBD_REQUEST_MAGIC 0x12560953 nbd_request include/linux/nbd.h
RED_MAGIC2 0x170fc2a5 (any) mm/slab.c
BAYCOM_MAGIC 0x19730510 baycom_state drivers/net/baycom_epp.c
@@ -116,7 +110,6 @@ ISDN_ASYNC_MAGIC 0x49344C01 modem_info include/linux/isdn.h
CTC_ASYNC_MAGIC 0x49344C01 ctc_tty_info drivers/s390/net/ctctty.c
ISDN_NET_MAGIC 0x49344C02 isdn_net_local_s drivers/isdn/i4l/isdn_net_lib.h
SAVEKMSG_MAGIC2 0x4B4D5347 savekmsg arch/*/amiga/config.c
-STLI_BOARDMAGIC 0x4bc6c825 stlibrd include/linux/istallion.h
CS_STATE_MAGIC 0x4c4f4749 cs_state sound/oss/cs46xx.c
SLAB_C_MAGIC 0x4f17a36d kmem_cache mm/slab.c
COW_MAGIC 0x4f4f4f4d cow_header_v1 arch/um/drivers/ubd_user.c
@@ -127,10 +120,8 @@ SCC_MAGIC 0x52696368 gs_port drivers/char/scc.h
SAVEKMSG_MAGIC1 0x53415645 savekmsg arch/*/amiga/config.c
GDA_MAGIC 0x58464552 gda arch/mips/include/asm/sn/gda.h
RED_MAGIC1 0x5a2cf071 (any) mm/slab.c
-STL_PORTMAGIC 0x5a7182c9 stlport include/linux/stallion.h
EEPROM_MAGIC_VALUE 0x5ab478d2 lanai_dev drivers/atm/lanai.c
HDLCDRV_MAGIC 0x5ac6e778 hdlcdrv_state include/linux/hdlcdrv.h
-EPCA_MAGIC 0x5c6df104 channel include/linux/epca.h
PCXX_MAGIC 0x5c6df104 channel drivers/char/pcxx.h
KV_MAGIC 0x5f4b565f kernel_vars_s arch/mips/include/asm/sn/klkernvars.h
I810_STATE_MAGIC 0x63657373 i810_state sound/oss/i810_audio.c
@@ -142,17 +133,14 @@ SLOT_MAGIC 0x67267322 slot drivers/hotplug/acpiphp.h
LO_MAGIC 0x68797548 nbd_device include/linux/nbd.h
OPROFILE_MAGIC 0x6f70726f super_block drivers/oprofile/oprofilefs.h
M3_STATE_MAGIC 0x734d724d m3_state sound/oss/maestro3.c
-STL_PANELMAGIC 0x7ef621a1 stlpanel include/linux/stallion.h
VMALLOC_MAGIC 0x87654320 snd_alloc_track sound/core/memory.c
KMALLOC_MAGIC 0x87654321 snd_alloc_track sound/core/memory.c
PWC_MAGIC 0x89DC10AB pwc_device drivers/usb/media/pwc.h
NBD_REPLY_MAGIC 0x96744668 nbd_reply include/linux/nbd.h
-STL_BOARDMAGIC 0xa2267f52 stlbrd include/linux/stallion.h
ENI155_MAGIC 0xa54b872d midway_eprom drivers/atm/eni.h
SCI_MAGIC 0xbabeface gs_port drivers/char/sh-sci.h
CODA_MAGIC 0xC0DAC0DA coda_file_info include/linux/coda_fs_i.h
DPMEM_MAGIC 0xc0ffee11 gdt_pci_sram drivers/scsi/gdth.h
-STLI_PORTMAGIC 0xe671c7a1 stliport include/linux/istallion.h
YAM_MAGIC 0xF10A7654 yam_port drivers/net/hamradio/yam.c
CCB_MAGIC 0xf2691ad2 ccb drivers/scsi/ncr53c8xx.c
QUEUE_MAGIC_FREE 0xf7e1c9a3 queue_entry drivers/scsi/arm/queue.c
diff --git a/Documentation/zh_CN/stable_kernel_rules.txt b/Documentation/zh_CN/stable_kernel_rules.txt
index b5b9b0ab02fd..26ea5ed7cd9c 100644
--- a/Documentation/zh_CN/stable_kernel_rules.txt
+++ b/Documentation/zh_CN/stable_kernel_rules.txt
@@ -42,7 +42,7 @@ Documentation/stable_kernel_rules.txt 的中文翻译
å‘稳定版代ç æ ‘æ交补ä¸çš„过程:
- - 在确认了补ä¸ç¬¦åˆä»¥ä¸Šçš„规则åŽï¼Œå°†è¡¥ä¸å‘é€åˆ°stable@kernel.org。
+ - 在确认了补ä¸ç¬¦åˆä»¥ä¸Šçš„规则åŽï¼Œå°†è¡¥ä¸å‘é€åˆ°stable@vger.kernel.org。
- 如果补ä¸è¢«æŽ¥å—到队列里,å‘é€è€…会收到一个ACK回å¤ï¼Œå¦‚果没有被接å—,收
到的是NAK回å¤ã€‚回å¤éœ€è¦å‡ å¤©çš„时间,这å–决于开å‘者的时间安排。
- 被接å—çš„è¡¥ä¸ä¼šè¢«åŠ åˆ°ç¨³å®šç‰ˆæœ¬é˜Ÿåˆ—里,等待其他开å‘者的审查。
diff --git a/MAINTAINERS b/MAINTAINERS
index 6dc67b1fdb50..672b80aa236c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -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>
@@ -3485,6 +3480,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 +3551,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
@@ -4203,9 +4204,11 @@ S: Maintained
F: fs/hpfs/
HSI SUBSYSTEM
-M: Sebastian Reichel <sre@debian.org>
+M: Sebastian Reichel <sre@kernel.org>
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-hsi.git
S: Maintained
F: Documentation/ABI/testing/sysfs-bus-hsi
+F: Documentation/hsi.txt
F: drivers/hsi/
F: include/linux/hsi/
F: include/uapi/linux/hsi/
@@ -4812,6 +4815,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 +5119,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 +5495,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
@@ -6404,6 +6420,7 @@ F: drivers/usb/*/*omap*
F: arch/arm/*omap*/usb*
OMAP GPIO DRIVER
+M: Javier Martinez Canillas <javier@dowhile0.org>
M: Santosh Shilimkar <santosh.shilimkar@ti.com>
M: Kevin Hilman <khilman@deeprootsystems.com>
L: linux-omap@vger.kernel.org
@@ -6500,10 +6517,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/
@@ -6782,7 +6799,7 @@ PERFORMANCE EVENTS SUBSYSTEM
M: Peter Zijlstra <a.p.zijlstra@chello.nl>
M: Paul Mackerras <paulus@samba.org>
M: Ingo Molnar <mingo@redhat.com>
-M: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
+M: Arnaldo Carvalho de Melo <acme@kernel.org>
L: linux-kernel@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git perf/core
S: Supported
@@ -7277,7 +7294,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 +7309,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 +7408,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 +7698,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
@@ -8315,7 +8338,7 @@ F: include/linux/compiler.h
SPEAR PLATFORM SUPPORT
M: Viresh Kumar <viresh.linux@gmail.com>
-M: Shiraz Hashim <shiraz.hashim@st.com>
+M: Shiraz Hashim <shiraz.linux.kernel@gmail.com>
L: spear-devel@list.st.com
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
W: http://www.st.com/spear
@@ -9098,6 +9121,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 +9977,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 +10022,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
diff --git a/Makefile b/Makefile
index 60ccbfe750a2..cdaa5b6a1c4d 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 3
PATCHLEVEL = 15
SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc8
NAME = Shuffling Zombie Juror
# *DOCUMENTATION*
diff --git a/arch/arc/include/asm/barrier.h b/arch/arc/include/asm/barrier.h
deleted file mode 100644
index c32245c3d1e9..000000000000
--- a/arch/arc/include/asm/barrier.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_BARRIER_H
-#define __ASM_BARRIER_H
-
-#ifndef __ASSEMBLY__
-
-/* TODO-vineetg: Need to see what this does, don't we need sync anywhere */
-#define mb() __asm__ __volatile__ ("" : : : "memory")
-#define rmb() mb()
-#define wmb() mb()
-#define set_mb(var, value) do { var = value; mb(); } while (0)
-#define set_wmb(var, value) do { var = value; wmb(); } while (0)
-#define read_barrier_depends() mb()
-
-/* TODO-vineetg verify the correctness of macros here */
-#ifdef CONFIG_SMP
-#define smp_mb() mb()
-#define smp_rmb() rmb()
-#define smp_wmb() wmb()
-#else
-#define smp_mb() barrier()
-#define smp_rmb() barrier()
-#define smp_wmb() barrier()
-#endif
-
-#define smp_read_barrier_depends() do { } while (0)
-
-#endif
-
-#endif
diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S
index 819dd5f7eb05..29b82adbf0b4 100644
--- a/arch/arc/kernel/entry.S
+++ b/arch/arc/kernel/entry.S
@@ -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]
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index ab438cb5af55..db3c5414223e 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -30,9 +30,9 @@ config ARM
select HAVE_ARCH_SECCOMP_FILTER if (AEABI && !OABI_COMPAT)
select HAVE_ARCH_TRACEHOOK
select HAVE_BPF_JIT
+ select HAVE_CC_STACKPROTECTOR
select HAVE_CONTEXT_TRACKING
select HAVE_C_RECORDMCOUNT
- select HAVE_CC_STACKPROTECTOR
select HAVE_DEBUG_KMEMLEAK
select HAVE_DMA_API_DEBUG
select HAVE_DMA_ATTRS
@@ -311,6 +311,7 @@ config ARCH_MULTIPLATFORM
select ARM_HAS_SG_CHAIN
select ARM_PATCH_PHYS_VIRT
select AUTO_ZRELADDR
+ select CLKSRC_OF
select COMMON_CLK
select GENERIC_CLOCKEVENTS
select MULTI_IRQ_HANDLER
@@ -422,8 +423,8 @@ config ARCH_EFM32
bool "Energy Micro efm32"
depends on !MMU
select ARCH_REQUIRE_GPIOLIB
- select AUTO_ZRELADDR
select ARM_NVIC
+ select AUTO_ZRELADDR
select CLKSRC_OF
select COMMON_CLK
select CPU_V7M
@@ -511,8 +512,8 @@ config ARCH_IXP4XX
bool "IXP4xx-based"
depends on MMU
select ARCH_HAS_DMA_SET_COHERENT_MASK
- select ARCH_SUPPORTS_BIG_ENDIAN
select ARCH_REQUIRE_GPIOLIB
+ select ARCH_SUPPORTS_BIG_ENDIAN
select CLKSRC_MMIO
select CPU_XSCALE
select DMABOUNCE if PCI
@@ -1110,9 +1111,9 @@ config ARM_NR_BANKS
default 8
config IWMMXT
- bool "Enable iWMMXt support" if !CPU_PJ4
- depends on CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_PJ4
- default y if PXA27x || PXA3xx || ARCH_MMP || CPU_PJ4
+ bool "Enable iWMMXt support"
+ depends on CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_PJ4 || CPU_PJ4B
+ default y if PXA27x || PXA3xx || ARCH_MMP || CPU_PJ4 || CPU_PJ4B
help
Enable support for iWMMXt context switching at run time if
running on a CPU that supports it.
@@ -1575,8 +1576,8 @@ config BIG_LITTLE
config BL_SWITCHER
bool "big.LITTLE switcher support"
depends on BIG_LITTLE && MCPM && HOTPLUG_CPU
- select CPU_PM
select ARM_CPU_SUSPEND
+ select CPU_PM
help
The big.LITTLE "switcher" provides the core functionality to
transparently handle transition between a cluster of A15's
@@ -1920,9 +1921,9 @@ config XEN
depends on CPU_V7 && !CPU_V6
depends on !GENERIC_ATOMIC64
depends on MMU
+ select ARCH_DMA_ADDR_T_64BIT
select ARM_PSCI
select SWIOTLB_XEN
- select ARCH_DMA_ADDR_T_64BIT
help
Say Y if you want to run Linux in a Virtual Machine on Xen on ARM.
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 4a2fc0bf6fc9..eab8ecbe69c1 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -1030,9 +1030,9 @@ config DEBUG_UART_PHYS
default 0x40100000 if DEBUG_PXA_UART1
default 0x42000000 if ARCH_GEMINI
default 0x7c0003f8 if FOOTBRIDGE
- default 0x80230000 if DEBUG_PICOXCELL_UART
default 0x80070000 if DEBUG_IMX23_UART
default 0x80074000 if DEBUG_IMX28_UART
+ default 0x80230000 if DEBUG_PICOXCELL_UART
default 0x808c0000 if ARCH_EP93XX
default 0x90020000 if DEBUG_NSPIRE_CLASSIC_UART || DEBUG_NSPIRE_CX_UART
default 0xb0090000 if DEBUG_VEXPRESS_UART0_CRX
@@ -1096,22 +1096,22 @@ config DEBUG_UART_VIRT
default 0xfeb26000 if DEBUG_RK3X_UART1
default 0xfeb30c00 if DEBUG_KEYSTONE_UART0
default 0xfeb31000 if DEBUG_KEYSTONE_UART1
- default 0xfec12000 if DEBUG_MVEBU_UART || DEBUG_MVEBU_UART_ALTERNATE
- default 0xfed60000 if DEBUG_RK29_UART0
- default 0xfed64000 if DEBUG_RK29_UART1 || DEBUG_RK3X_UART2
- default 0xfed68000 if DEBUG_RK29_UART2 || DEBUG_RK3X_UART3
default 0xfec02000 if DEBUG_SOCFPGA_UART
+ default 0xfec12000 if DEBUG_MVEBU_UART || DEBUG_MVEBU_UART_ALTERNATE
default 0xfec20000 if DEBUG_DAVINCI_DMx_UART0
default 0xfed0c000 if DEBUG_DAVINCI_DA8XX_UART1
default 0xfed0d000 if DEBUG_DAVINCI_DA8XX_UART2
default 0xfed12000 if ARCH_KIRKWOOD
+ default 0xfed60000 if DEBUG_RK29_UART0
+ default 0xfed64000 if DEBUG_RK29_UART1 || DEBUG_RK3X_UART2
+ default 0xfed68000 if DEBUG_RK29_UART2 || DEBUG_RK3X_UART3
default 0xfedc0000 if ARCH_EP93XX
default 0xfee003f8 if FOOTBRIDGE
default 0xfee20000 if DEBUG_NSPIRE_CLASSIC_UART || DEBUG_NSPIRE_CX_UART
- default 0xfef36000 if DEBUG_HIGHBANK_UART
default 0xfee82340 if ARCH_IOP13XX
default 0xfef00000 if ARCH_IXP4XX && !CPU_BIG_ENDIAN
default 0xfef00003 if ARCH_IXP4XX && CPU_BIG_ENDIAN
+ default 0xfef36000 if DEBUG_HIGHBANK_UART
default 0xfefff700 if ARCH_IOP33X
default 0xff003000 if DEBUG_U300_UART
default DEBUG_UART_PHYS if !MMU
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 35c146f31e46..377b7c364033 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -51,10 +51,9 @@ dtb-$(CONFIG_ARCH_AT91) += sama5d36ek.dtb
dtb-$(CONFIG_ARCH_ATLAS6) += atlas6-evb.dtb
dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-b.dtb
+dtb-$(CONFIG_ARCH_BCM_5301X) += bcm4708-netgear-r6250.dtb
dtb-$(CONFIG_ARCH_BCM_MOBILE) += bcm28155-ap.dtb \
bcm21664-garnet.dtb
-dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-b.dtb
-dtb-$(CONFIG_ARCH_BCM_5301X) += bcm4708-netgear-r6250.dtb
dtb-$(CONFIG_ARCH_BERLIN) += \
berlin2-sony-nsz-gs7.dtb \
berlin2cd-google-chromecast.dtb
@@ -246,6 +245,7 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \
omap3-sbc-t3730.dtb \
omap3-devkit8000.dtb \
omap3-beagle-xm.dtb \
+ omap3-beagle-xm-ab.dtb \
omap3-evm.dtb \
omap3-evm-37xx.dtb \
omap3-ldp.dtb \
@@ -294,13 +294,6 @@ dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb.dtb
dtb-$(CONFIG_ARCH_QCOM) += qcom-msm8660-surf.dtb \
qcom-msm8960-cdp.dtb \
qcom-apq8074-dragonboard.dtb
-dtb-$(CONFIG_ARCH_U8500) += ste-snowball.dtb \
- ste-hrefprev60-stuib.dtb \
- ste-hrefprev60-tvk.dtb \
- ste-hrefv60plus-stuib.dtb \
- ste-hrefv60plus-tvk.dtb \
- ste-ccu8540.dtb \
- ste-ccu9540.dtb
dtb-$(CONFIG_ARCH_S3C24XX) += s3c2416-smdk2416.dtb
dtb-$(CONFIG_ARCH_S3C64XX) += s3c6410-mini6410.dtb \
s3c6410-smdk6410.dtb
@@ -369,9 +362,16 @@ dtb-$(CONFIG_ARCH_TEGRA) += tegra20-harmony.dtb \
tegra30-cardhu-a04.dtb \
tegra114-dalmore.dtb \
tegra124-venice2.dtb
+dtb-$(CONFIG_ARCH_U300) += ste-u300.dtb
+dtb-$(CONFIG_ARCH_U8500) += ste-snowball.dtb \
+ ste-hrefprev60-stuib.dtb \
+ ste-hrefprev60-tvk.dtb \
+ ste-hrefv60plus-stuib.dtb \
+ ste-hrefv60plus-tvk.dtb \
+ ste-ccu8540.dtb \
+ ste-ccu9540.dtb
dtb-$(CONFIG_ARCH_VERSATILE) += versatile-ab.dtb \
versatile-pb.dtb
-dtb-$(CONFIG_ARCH_U300) += ste-u300.dtb
dtb-$(CONFIG_ARCH_VEXPRESS) += vexpress-v2p-ca5s.dtb \
vexpress-v2p-ca9.dtb \
vexpress-v2p-ca15-tc1.dtb \
diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
index e3f27ec31718..2e7d932887b5 100644
--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
+++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
@@ -183,7 +183,7 @@
&usb {
status = "okay";
- control@44e10000 {
+ control@44e10620 {
status = "okay";
};
@@ -204,7 +204,7 @@
dr_mode = "host";
};
- dma-controller@07402000 {
+ dma-controller@47402000 {
status = "okay";
};
};
diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
index 28ae040e7c3d..6028217ace0f 100644
--- a/arch/arm/boot/dts/am335x-evm.dts
+++ b/arch/arm/boot/dts/am335x-evm.dts
@@ -301,8 +301,8 @@
am335x_evm_audio_pins: am335x_evm_audio_pins {
pinctrl-single,pins = <
- 0x10c (PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_rx_dv.mcasp1_aclkx */
- 0x110 (PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_txd3.mcasp1_fsx */
+ 0x10c (PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_crs.mcasp1_aclkx */
+ 0x110 (PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_rxerr.mcasp1_fsx */
0x108 (PIN_OUTPUT_PULLDOWN | MUX_MODE4) /* mii1_col.mcasp1_axr2 */
0x144 (PIN_INPUT_PULLDOWN | MUX_MODE4) /* rmii1_ref_clk.mcasp1_axr3 */
>;
@@ -331,7 +331,7 @@
&usb {
status = "okay";
- control@44e10000 {
+ control@44e10620 {
status = "okay";
};
@@ -352,7 +352,7 @@
dr_mode = "host";
};
- dma-controller@07402000 {
+ dma-controller@47402000 {
status = "okay";
};
};
diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts
index ec08f6f677c3..ab238850a7b2 100644
--- a/arch/arm/boot/dts/am335x-evmsk.dts
+++ b/arch/arm/boot/dts/am335x-evmsk.dts
@@ -364,7 +364,7 @@
&usb {
status = "okay";
- control@44e10000 {
+ control@44e10620 {
status = "okay";
};
@@ -385,7 +385,7 @@
dr_mode = "host";
};
- dma-controller@07402000 {
+ dma-controller@47402000 {
status = "okay";
};
};
diff --git a/arch/arm/boot/dts/am335x-igep0033.dtsi b/arch/arm/boot/dts/am335x-igep0033.dtsi
index 7063311a58d9..9f22c189f636 100644
--- a/arch/arm/boot/dts/am335x-igep0033.dtsi
+++ b/arch/arm/boot/dts/am335x-igep0033.dtsi
@@ -118,7 +118,6 @@
reg = <0 0 0>; /* CS0, offset 0 */
nand-bus-width = <8>;
ti,nand-ecc-opt = "bch8";
- gpmc,device-nand = "true";
gpmc,device-width = <1>;
gpmc,sync-clk-ps = <0>;
gpmc,cs-on-ns = <0>;
@@ -202,7 +201,7 @@
&usb {
status = "okay";
- control@44e10000 {
+ control@44e10620 {
status = "okay";
};
@@ -223,7 +222,7 @@
dr_mode = "host";
};
- dma-controller@07402000 {
+ dma-controller@47402000 {
status = "okay";
};
};
diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index 9770e35f2536..7ad75b4e0663 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -72,7 +72,7 @@
};
/*
- * The soc node represents the soc top level view. It is uses for IPs
+ * The soc node represents the soc top level view. It is used for IPs
* that are not memory mapped in the MPU view or for the MPU itself.
*/
soc {
@@ -94,8 +94,8 @@
/*
* XXX: Use a flat representation of the AM33XX interconnect.
- * The real AM33XX interconnect network is quite complex.Since
- * that will not bring real advantage to represent that in DT
+ * The real AM33XX interconnect network is quite complex. Since
+ * it will not bring real advantage to represent that in DT
* for the moment, just use a fake OCP bus entry to represent
* the whole bus hierarchy.
*/
@@ -144,7 +144,7 @@
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>;
@@ -802,7 +802,7 @@
<0x46000000 0x400000>;
reg-names = "mpu", "dat";
interrupts = <80>, <81>;
- interrupts-names = "tx", "rx";
+ interrupt-names = "tx", "rx";
status = "disabled";
dmas = <&edma 8>,
<&edma 9>;
@@ -816,7 +816,7 @@
<0x46400000 0x400000>;
reg-names = "mpu", "dat";
interrupts = <82>, <83>;
- interrupts-names = "tx", "rx";
+ interrupt-names = "tx", "rx";
status = "disabled";
dmas = <&edma 10>,
<&edma 11>;
diff --git a/arch/arm/boot/dts/am3517.dtsi b/arch/arm/boot/dts/am3517.dtsi
index 788391f91684..5a452fdd7c5d 100644
--- a/arch/arm/boot/dts/am3517.dtsi
+++ b/arch/arm/boot/dts/am3517.dtsi
@@ -62,5 +62,21 @@
};
};
+&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"
diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi
index 36d523a26831..d1f8707ff1df 100644
--- a/arch/arm/boot/dts/am4372.dtsi
+++ b/arch/arm/boot/dts/am4372.dtsi
@@ -691,7 +691,7 @@
<0x46000000 0x400000>;
reg-names = "mpu", "dat";
interrupts = <80>, <81>;
- interrupts-names = "tx", "rx";
+ interrupt-names = "tx", "rx";
status = "disabled";
dmas = <&edma 8>,
<&edma 9>;
@@ -705,7 +705,7 @@
<0x46400000 0x400000>;
reg-names = "mpu", "dat";
interrupts = <82>, <83>;
- interrupts-names = "tx", "rx";
+ interrupt-names = "tx", "rx";
status = "disabled";
dmas = <&edma 10>,
<&edma 11>;
diff --git a/arch/arm/boot/dts/am437x-gp-evm.dts b/arch/arm/boot/dts/am437x-gp-evm.dts
index df8798e8bd25..a055f7f0f14a 100644
--- a/arch/arm/boot/dts/am437x-gp-evm.dts
+++ b/arch/arm/boot/dts/am437x-gp-evm.dts
@@ -117,6 +117,11 @@
status = "okay";
};
+&gpio5 {
+ status = "okay";
+ ti,no-reset-on-init;
+};
+
&mmc1 {
status = "okay";
vmmc-supply = <&vmmcsd_fixed>;
diff --git a/arch/arm/boot/dts/armada-370-db.dts b/arch/arm/boot/dts/armada-370-db.dts
index 82f238a9063f..3383c4b66803 100644
--- a/arch/arm/boot/dts/armada-370-db.dts
+++ b/arch/arm/boot/dts/armada-370-db.dts
@@ -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";
diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi b/arch/arm/boot/dts/armada-370-xp.dtsi
index bbb40f62037d..bb77970c0b12 100644
--- a/arch/arm/boot/dts/armada-370-xp.dtsi
+++ b/arch/arm/boot/dts/armada-370-xp.dtsi
@@ -230,6 +230,7 @@
#size-cells = <0>;
compatible = "marvell,orion-mdio";
reg = <0x72004 0x4>;
+ clocks = <&gateclk 4>;
};
eth1: ethernet@74000 {
diff --git a/arch/arm/boot/dts/armada-375-db.dts b/arch/arm/boot/dts/armada-375-db.dts
index 9378d3136b41..0451124e8ebf 100644
--- a/arch/arm/boot/dts/armada-375-db.dts
+++ b/arch/arm/boot/dts/armada-375-db.dts
@@ -79,6 +79,11 @@
};
};
+ sata@a0000 {
+ status = "okay";
+ nr-ports = <2>;
+ };
+
nand: nand@d0000 {
pinctrl-0 = <&nand_pins>;
pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/armada-380.dtsi b/arch/arm/boot/dts/armada-380.dtsi
index 068031f0f263..6d0f03c98ee9 100644
--- a/arch/arm/boot/dts/armada-380.dtsi
+++ b/arch/arm/boot/dts/armada-380.dtsi
@@ -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>;
diff --git a/arch/arm/boot/dts/armada-385.dtsi b/arch/arm/boot/dts/armada-385.dtsi
index e2919f02e1d4..da801964a257 100644
--- a/arch/arm/boot/dts/armada-385.dtsi
+++ b/arch/arm/boot/dts/armada-385.dtsi
@@ -110,7 +110,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>;
@@ -131,7 +131,7 @@
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>;
diff --git a/arch/arm/boot/dts/armada-38x.dtsi b/arch/arm/boot/dts/armada-38x.dtsi
index a064f59da02d..ca8813bb99ba 100644
--- a/arch/arm/boot/dts/armada-38x.dtsi
+++ b/arch/arm/boot/dts/armada-38x.dtsi
@@ -336,6 +336,7 @@
#size-cells = <0>;
compatible = "marvell,orion-mdio";
reg = <0x72004 0x4>;
+ clocks = <&gateclk 4>;
};
coredivclk: clock@e4250 {
diff --git a/arch/arm/boot/dts/armada-xp-db.dts b/arch/arm/boot/dts/armada-xp-db.dts
index 448373c4b0e5..90f0bf6f9271 100644
--- a/arch/arm/boot/dts/armada-xp-db.dts
+++ b/arch/arm/boot/dts/armada-xp-db.dts
@@ -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>;
diff --git a/arch/arm/boot/dts/armada-xp-gp.dts b/arch/arm/boot/dts/armada-xp-gp.dts
index 61bda687f782..0c756421ae6a 100644
--- a/arch/arm/boot/dts/armada-xp-gp.dts
+++ b/arch/arm/boot/dts/armada-xp-gp.dts
@@ -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>;
@@ -146,22 +146,22 @@
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 */
diff --git a/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts b/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts
index 985948ce67b3..5d42feb31049 100644
--- a/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts
+++ b/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts
@@ -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>;
diff --git a/arch/arm/boot/dts/at91-sama5d3_xplained.dts b/arch/arm/boot/dts/at91-sama5d3_xplained.dts
index ce1375595e5f..4537259ce529 100644
--- a/arch/arm/boot/dts/at91-sama5d3_xplained.dts
+++ b/arch/arm/boot/dts/at91-sama5d3_xplained.dts
@@ -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";
};
diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi
index 366fc2cbcd64..c0e0eae16a27 100644
--- a/arch/arm/boot/dts/at91sam9260.dtsi
+++ b/arch/arm/boot/dts/at91sam9260.dtsi
@@ -641,7 +641,7 @@
trigger@3 {
reg = <3>;
trigger-name = "external";
- trigger-value = <0x13>;
+ trigger-value = <0xd>;
trigger-external;
};
};
diff --git a/arch/arm/boot/dts/at91sam9261.dtsi b/arch/arm/boot/dts/at91sam9261.dtsi
index e21dda0e8986..3be973e9889a 100644
--- a/arch/arm/boot/dts/at91sam9261.dtsi
+++ b/arch/arm/boot/dts/at91sam9261.dtsi
@@ -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";
diff --git a/arch/arm/boot/dts/at91sam9rl.dtsi b/arch/arm/boot/dts/at91sam9rl.dtsi
index 63e1784d272c..92a52faebef7 100644
--- a/arch/arm/boot/dts/at91sam9rl.dtsi
+++ b/arch/arm/boot/dts/at91sam9rl.dtsi
@@ -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>
diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
index 1c0f8e1893ae..149b55099935 100644
--- a/arch/arm/boot/dts/dra7.dtsi
+++ b/arch/arm/boot/dts/dra7.dtsi
@@ -80,7 +80,7 @@
};
/*
- * The soc node represents the soc top level view. It is uses for IPs
+ * The soc node represents the soc top level view. It is used for IPs
* that are not memory mapped in the MPU view or for the MPU itself.
*/
soc {
@@ -94,7 +94,7 @@
/*
* XXX: Use a flat representation of the SOC interconnect.
* The real OMAP interconnect network is quite complex.
- * Since that will not bring real advantage to represent that in DT for
+ * Since it will not bring real advantage to represent that in DT for
* the moment, just use a fake OCP bus entry to represent the whole bus
* hierarchy.
*/
diff --git a/arch/arm/boot/dts/dra7xx-clocks.dtsi b/arch/arm/boot/dts/dra7xx-clocks.dtsi
index e96da9a898ad..cfb8fc753f50 100644
--- a/arch/arm/boot/dts/dra7xx-clocks.dtsi
+++ b/arch/arm/boot/dts/dra7xx-clocks.dtsi
@@ -1640,7 +1640,7 @@
#clock-cells = <0>;
compatible = "ti,mux-clock";
clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
- ti,bit-shift = <28>;
+ ti,bit-shift = <24>;
reg = <0x1860>;
};
diff --git a/arch/arm/boot/dts/exynos4412-trats2.dts b/arch/arm/boot/dts/exynos4412-trats2.dts
index 9583563dd0ef..8a558b7ac999 100644
--- a/arch/arm/boot/dts/exynos4412-trats2.dts
+++ b/arch/arm/boot/dts/exynos4412-trats2.dts
@@ -503,7 +503,7 @@
status = "okay";
ak8975@0c {
- compatible = "ak,ak8975";
+ compatible = "asahi-kasei,ak8975";
reg = <0x0c>;
gpios = <&gpj0 7 0>;
};
diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts
index 090f9830b129..cde19c818667 100644
--- a/arch/arm/boot/dts/exynos5250-arndale.dts
+++ b/arch/arm/boot/dts/exynos5250-arndale.dts
@@ -107,6 +107,7 @@
regulator-name = "VDD_IOPERI_1.8V";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
+ regulator-always-on;
op_mode = <1>;
};
diff --git a/arch/arm/boot/dts/exynos5420-arndale-octa.dts b/arch/arm/boot/dts/exynos5420-arndale-octa.dts
index 80a3bf4c5986..896a2a6619e0 100644
--- a/arch/arm/boot/dts/exynos5420-arndale-octa.dts
+++ b/arch/arm/boot/dts/exynos5420-arndale-octa.dts
@@ -364,16 +364,4 @@
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";
- };
- };
};
diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index c3a9a66c5767..b69fbcb7dcb8 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -219,16 +219,6 @@
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>;
@@ -336,6 +326,13 @@
#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";
};
};
@@ -385,7 +382,7 @@
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";
@@ -401,7 +398,7 @@
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";
@@ -417,7 +414,7 @@
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";
@@ -730,6 +727,5 @@
interrupts = <0 112 0>;
clocks = <&clock 471>;
clock-names = "secss";
- samsung,power-domain = <&g2d_pd>;
};
};
diff --git a/arch/arm/boot/dts/imx25.dtsi b/arch/arm/boot/dts/imx25.dtsi
index 32f760e24898..ea323f09dc78 100644
--- a/arch/arm/boot/dts/imx25.dtsi
+++ b/arch/arm/boot/dts/imx25.dtsi
@@ -56,6 +56,7 @@
osc {
compatible = "fsl,imx-osc", "fixed-clock";
+ #clock-cells = <0>;
clock-frequency = <24000000>;
};
};
diff --git a/arch/arm/boot/dts/imx27-apf27.dts b/arch/arm/boot/dts/imx27-apf27.dts
index 09f57b39e3ef..73aae4f5e539 100644
--- a/arch/arm/boot/dts/imx27-apf27.dts
+++ b/arch/arm/boot/dts/imx27-apf27.dts
@@ -29,6 +29,7 @@
osc26m {
compatible = "fsl,imx-osc26m", "fixed-clock";
+ #clock-cells = <0>;
clock-frequency = <0>;
};
};
diff --git a/arch/arm/boot/dts/imx27.dtsi b/arch/arm/boot/dts/imx27.dtsi
index 6279e0b4f768..137e010eab35 100644
--- a/arch/arm/boot/dts/imx27.dtsi
+++ b/arch/arm/boot/dts/imx27.dtsi
@@ -48,6 +48,7 @@
osc26m {
compatible = "fsl,imx-osc26m", "fixed-clock";
+ #clock-cells = <0>;
clock-frequency = <26000000>;
};
};
diff --git a/arch/arm/boot/dts/imx50.dtsi b/arch/arm/boot/dts/imx50.dtsi
index 0c75fe3deb35..9c89d1ca97c2 100644
--- a/arch/arm/boot/dts/imx50.dtsi
+++ b/arch/arm/boot/dts/imx50.dtsi
@@ -53,21 +53,25 @@
ckil {
compatible = "fsl,imx-ckil", "fixed-clock";
+ #clock-cells = <0>;
clock-frequency = <32768>;
};
ckih1 {
compatible = "fsl,imx-ckih1", "fixed-clock";
+ #clock-cells = <0>;
clock-frequency = <22579200>;
};
ckih2 {
compatible = "fsl,imx-ckih2", "fixed-clock";
+ #clock-cells = <0>;
clock-frequency = <0>;
};
osc {
compatible = "fsl,imx-osc", "fixed-clock";
+ #clock-cells = <0>;
clock-frequency = <24000000>;
};
};
diff --git a/arch/arm/boot/dts/imx51.dtsi b/arch/arm/boot/dts/imx51.dtsi
index 5f8216d08f6b..150bb4e2f744 100644
--- a/arch/arm/boot/dts/imx51.dtsi
+++ b/arch/arm/boot/dts/imx51.dtsi
@@ -50,21 +50,25 @@
ckil {
compatible = "fsl,imx-ckil", "fixed-clock";
+ #clock-cells = <0>;
clock-frequency = <32768>;
};
ckih1 {
compatible = "fsl,imx-ckih1", "fixed-clock";
+ #clock-cells = <0>;
clock-frequency = <0>;
};
ckih2 {
compatible = "fsl,imx-ckih2", "fixed-clock";
+ #clock-cells = <0>;
clock-frequency = <0>;
};
osc {
compatible = "fsl,imx-osc", "fixed-clock";
+ #clock-cells = <0>;
clock-frequency = <24000000>;
};
};
diff --git a/arch/arm/boot/dts/imx53-m53evk.dts b/arch/arm/boot/dts/imx53-m53evk.dts
index f6d3ac3e5587..d5d146a8b149 100644
--- a/arch/arm/boot/dts/imx53-m53evk.dts
+++ b/arch/arm/boot/dts/imx53-m53evk.dts
@@ -17,7 +17,8 @@
compatible = "denx,imx53-m53evk", "fsl,imx53";
memory {
- reg = <0x70000000 0x20000000>;
+ reg = <0x70000000 0x20000000>,
+ <0xb0000000 0x20000000>;
};
soc {
@@ -193,17 +194,17 @@
irq-trigger = <0x1>;
stmpe_touchscreen {
- compatible = "stmpe,ts";
+ compatible = "st,stmpe-ts";
reg = <0>;
- ts,sample-time = <4>;
- ts,mod-12b = <1>;
- ts,ref-sel = <0>;
- ts,adc-freq = <1>;
- ts,ave-ctrl = <3>;
- ts,touch-det-delay = <3>;
- ts,settling = <4>;
- ts,fraction-z = <7>;
- ts,i-drive = <1>;
+ st,sample-time = <4>;
+ st,mod-12b = <1>;
+ st,ref-sel = <0>;
+ st,adc-freq = <1>;
+ st,ave-ctrl = <3>;
+ st,touch-det-delay = <3>;
+ st,settling = <4>;
+ st,fraction-z = <7>;
+ st,i-drive = <1>;
};
};
diff --git a/arch/arm/boot/dts/imx53-mba53.dts b/arch/arm/boot/dts/imx53-mba53.dts
index 7c8c12969892..a3431d784870 100644
--- a/arch/arm/boot/dts/imx53-mba53.dts
+++ b/arch/arm/boot/dts/imx53-mba53.dts
@@ -244,7 +244,7 @@
&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>;
diff --git a/arch/arm/boot/dts/imx53-qsb-common.dtsi b/arch/arm/boot/dts/imx53-qsb-common.dtsi
index 3f825a6813da..ede04fa4161f 100644
--- a/arch/arm/boot/dts/imx53-qsb-common.dtsi
+++ b/arch/arm/boot/dts/imx53-qsb-common.dtsi
@@ -14,7 +14,8 @@
/ {
memory {
- reg = <0x70000000 0x40000000>;
+ reg = <0x70000000 0x20000000>,
+ <0xb0000000 0x20000000>;
};
display0: display@di0 {
diff --git a/arch/arm/boot/dts/imx53-tx53-x03x.dts b/arch/arm/boot/dts/imx53-tx53-x03x.dts
index 0217dde3b36b..3b73e81dc3f0 100644
--- a/arch/arm/boot/dts/imx53-tx53-x03x.dts
+++ b/arch/arm/boot/dts/imx53-tx53-x03x.dts
@@ -25,12 +25,17 @@
soc {
display: display@di0 {
compatible = "fsl,imx-parallel-display";
- crtcs = <&ipu 0>;
interface-pix-fmt = "rgb24";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_rgb24_vga1>;
status = "okay";
+ port {
+ display0_in: endpoint {
+ remote-endpoint = <&ipu_di0_disp0>;
+ };
+ };
+
display-timings {
VGA {
clock-frequency = <25200000>;
@@ -293,6 +298,10 @@
};
};
+&ipu_di0_disp0 {
+ remote-endpoint = <&display0_in>;
+};
+
&kpp {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_kpp>;
diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi
index b57ab57740f6..6a1bf4ff83d5 100644
--- a/arch/arm/boot/dts/imx53.dtsi
+++ b/arch/arm/boot/dts/imx53.dtsi
@@ -70,21 +70,25 @@
ckil {
compatible = "fsl,imx-ckil", "fixed-clock";
+ #clock-cells = <0>;
clock-frequency = <32768>;
};
ckih1 {
compatible = "fsl,imx-ckih1", "fixed-clock";
+ #clock-cells = <0>;
clock-frequency = <22579200>;
};
ckih2 {
compatible = "fsl,imx-ckih2", "fixed-clock";
+ #clock-cells = <0>;
clock-frequency = <0>;
};
osc {
compatible = "fsl,imx-osc", "fixed-clock";
+ #clock-cells = <0>;
clock-frequency = <24000000>;
};
};
@@ -111,7 +115,7 @@
#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>,
@@ -430,7 +434,7 @@
port {
lvds1_in: endpoint {
- remote-endpoint = <&ipu_di0_lvds0>;
+ remote-endpoint = <&ipu_di1_lvds1>;
};
};
};
diff --git a/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts b/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts
index a63bbb3d46bb..e4ae38fd0269 100644
--- a/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts
+++ b/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts
@@ -19,7 +19,10 @@
compatible = "dmo,imx6q-edmqmx6", "fsl,imx6q";
aliases {
- gpio7 = &stmpe_gpio;
+ gpio7 = &stmpe_gpio1;
+ gpio8 = &stmpe_gpio2;
+ stmpe-i2c0 = &stmpe1;
+ stmpe-i2c1 = &stmpe2;
};
memory {
@@ -40,13 +43,15 @@
regulator-always-on;
};
- reg_usb_otg_vbus: regulator@1 {
+ reg_usb_otg_switch: regulator@1 {
compatible = "regulator-fixed";
reg = <1>;
- regulator-name = "usb_otg_vbus";
+ regulator-name = "usb_otg_switch";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
gpio = <&gpio7 12 0>;
+ regulator-boot-on;
+ regulator-always-on;
};
reg_usb_host1: regulator@2 {
@@ -65,23 +70,23 @@
led-blue {
label = "blue";
- gpios = <&stmpe_gpio 8 GPIO_ACTIVE_HIGH>;
+ gpios = <&stmpe_gpio1 8 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "heartbeat";
};
led-green {
label = "green";
- gpios = <&stmpe_gpio 9 GPIO_ACTIVE_HIGH>;
+ gpios = <&stmpe_gpio1 9 GPIO_ACTIVE_HIGH>;
};
led-pink {
label = "pink";
- gpios = <&stmpe_gpio 10 GPIO_ACTIVE_HIGH>;
+ gpios = <&stmpe_gpio1 10 GPIO_ACTIVE_HIGH>;
};
led-red {
label = "red";
- gpios = <&stmpe_gpio 11 GPIO_ACTIVE_HIGH>;
+ gpios = <&stmpe_gpio1 11 GPIO_ACTIVE_HIGH>;
};
};
};
@@ -99,7 +104,8 @@
clock-frequency = <100000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c2
- &pinctrl_stmpe>;
+ &pinctrl_stmpe1
+ &pinctrl_stmpe2>;
status = "okay";
pmic: pfuze100@08 {
@@ -205,13 +211,25 @@
};
};
- stmpe: stmpe1601@40 {
+ stmpe1: stmpe1601@40 {
compatible = "st,stmpe1601";
reg = <0x40>;
interrupts = <30 0>;
interrupt-parent = <&gpio3>;
- stmpe_gpio: stmpe_gpio {
+ stmpe_gpio1: stmpe_gpio {
+ #gpio-cells = <2>;
+ compatible = "st,stmpe-gpio";
+ };
+ };
+
+ stmpe2: stmpe1601@44 {
+ compatible = "st,stmpe1601";
+ reg = <0x44>;
+ interrupts = <2 0>;
+ interrupt-parent = <&gpio5>;
+
+ stmpe_gpio2: stmpe_gpio {
#gpio-cells = <2>;
compatible = "st,stmpe-gpio";
};
@@ -273,10 +291,14 @@
>;
};
- pinctrl_stmpe: stmpegrp {
+ pinctrl_stmpe1: stmpe1grp {
fsl,pins = <MX6QDL_PAD_EIM_D30__GPIO3_IO30 0x80000000>;
};
+ pinctrl_stmpe2: stmpe2grp {
+ fsl,pins = <MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x80000000>;
+ };
+
pinctrl_uart1: uart1grp {
fsl,pins = <
MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1
@@ -293,7 +315,7 @@
pinctrl_usbotg: usbotggrp {
fsl,pins = <
- MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
+ MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
>;
};
@@ -344,11 +366,11 @@
&usbh1 {
vbus-supply = <&reg_usb_host1>;
disable-over-current;
+ dr_mode = "host";
status = "okay";
};
&usbotg {
- vbus-supply = <&reg_usb_otg_vbus>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usbotg>;
disable-over-current;
diff --git a/arch/arm/boot/dts/imx6q-gw5400-a.dts b/arch/arm/boot/dts/imx6q-gw5400-a.dts
index 902f98310481..e51bb3f0fd56 100644
--- a/arch/arm/boot/dts/imx6q-gw5400-a.dts
+++ b/arch/arm/boot/dts/imx6q-gw5400-a.dts
@@ -487,9 +487,6 @@
&ldb {
status = "okay";
- lvds-channel@0 {
- crtcs = <&ipu1 0>, <&ipu1 1>, <&ipu2 0>, <&ipu2 1>;
- };
};
&pcie {
diff --git a/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
index 8e99c9a9bc76..035d3a85c318 100644
--- a/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
@@ -436,9 +436,6 @@
&ldb {
status = "okay";
- lvds-channel@0 {
- crtcs = <&ipu1 0>, <&ipu1 1>;
- };
};
&pcie {
diff --git a/arch/arm/boot/dts/imx6qdl-microsom-ar8035.dtsi b/arch/arm/boot/dts/imx6qdl-microsom-ar8035.dtsi
index a3cb2fff8f61..d16066608e21 100644
--- a/arch/arm/boot/dts/imx6qdl-microsom-ar8035.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-microsom-ar8035.dtsi
@@ -26,25 +26,25 @@
/* GPIO16 -> AR8035 25MHz */
MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0xc0000000
MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x80000000
- MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0
- MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0
- MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0
- MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0
- MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030
+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030
+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030
+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030
+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030
/* AR8035 CLK_25M --> ENET_REF_CLK (V22) */
MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x0a0b1
/* AR8035 pin strapping: IO voltage: pull up */
- MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030
/* AR8035 pin strapping: PHYADDR#0: pull down */
- MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x130b0
+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x13030
/* AR8035 pin strapping: PHYADDR#1: pull down */
- MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x130b0
+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x13030
/* AR8035 pin strapping: MODE#1: pull up */
- MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030
/* AR8035 pin strapping: MODE#3: pull up */
- MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030
/* AR8035 pin strapping: MODE#0: pull down */
- MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x130b0
+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x13030
/*
* As the RMII pins are also connected to RGMII
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index 55cb926fa3f7..eca0971d4db1 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -10,6 +10,8 @@
* http://www.gnu.org/copyleft/gpl.html
*/
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
#include "skeleton.dtsi"
/ {
@@ -46,8 +48,6 @@
intc: interrupt-controller@00a01000 {
compatible = "arm,cortex-a9-gic";
#interrupt-cells = <3>;
- #address-cells = <1>;
- #size-cells = <1>;
interrupt-controller;
reg = <0x00a01000 0x1000>,
<0x00a00100 0x100>;
@@ -59,16 +59,19 @@
ckil {
compatible = "fsl,imx-ckil", "fixed-clock";
+ #clock-cells = <0>;
clock-frequency = <32768>;
};
ckih1 {
compatible = "fsl,imx-ckih1", "fixed-clock";
+ #clock-cells = <0>;
clock-frequency = <0>;
};
osc {
compatible = "fsl,imx-osc", "fixed-clock";
+ #clock-cells = <0>;
clock-frequency = <24000000>;
};
};
@@ -138,6 +141,12 @@
0x82000000 0 0x01000000 0x01000000 0 0x00f00000>; /* non-prefetchable memory */
num-lanes = <1>;
interrupts = <0 123 IRQ_TYPE_LEVEL_HIGH>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0x7>;
+ interrupt-map = <0 0 0 1 &intc GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 2 &intc GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 3 &intc GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 4 &intc GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks 189>, <&clks 187>, <&clks 206>, <&clks 144>;
clock-names = "pcie_ref_125m", "sata_ref_100m", "lvds_gate", "pcie_axi";
status = "disabled";
diff --git a/arch/arm/boot/dts/imx6sl-evk.dts b/arch/arm/boot/dts/imx6sl-evk.dts
index 864d8dfb51ca..a8d9a93fab85 100644
--- a/arch/arm/boot/dts/imx6sl-evk.dts
+++ b/arch/arm/boot/dts/imx6sl-evk.dts
@@ -282,6 +282,7 @@
MX6SL_PAD_ECSPI1_MISO__ECSPI1_MISO 0x100b1
MX6SL_PAD_ECSPI1_MOSI__ECSPI1_MOSI 0x100b1
MX6SL_PAD_ECSPI1_SCLK__ECSPI1_SCLK 0x100b1
+ MX6SL_PAD_ECSPI1_SS0__GPIO4_IO11 0x80000000
>;
};
diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi
index 3cb4941afeef..d26b099260a3 100644
--- a/arch/arm/boot/dts/imx6sl.dtsi
+++ b/arch/arm/boot/dts/imx6sl.dtsi
@@ -68,8 +68,6 @@
intc: interrupt-controller@00a01000 {
compatible = "arm,cortex-a9-gic";
#interrupt-cells = <3>;
- #address-cells = <1>;
- #size-cells = <1>;
interrupt-controller;
reg = <0x00a01000 0x1000>,
<0x00a00100 0x100>;
@@ -81,11 +79,13 @@
ckil {
compatible = "fixed-clock";
+ #clock-cells = <0>;
clock-frequency = <32768>;
};
osc {
compatible = "fixed-clock";
+ #clock-cells = <0>;
clock-frequency = <24000000>;
};
};
diff --git a/arch/arm/boot/dts/kirkwood-b3.dts b/arch/arm/boot/dts/kirkwood-b3.dts
index 40791053106b..6becedebaa4e 100644
--- a/arch/arm/boot/dts/kirkwood-b3.dts
+++ b/arch/arm/boot/dts/kirkwood-b3.dts
@@ -75,7 +75,7 @@
m25p16@0 {
#address-cells = <1>;
#size-cells = <1>;
- compatible = "m25p16";
+ compatible = "st,m25p16";
reg = <0>;
spi-max-frequency = <40000000>;
mode = <0>;
diff --git a/arch/arm/boot/dts/kirkwood-cloudbox.dts b/arch/arm/boot/dts/kirkwood-cloudbox.dts
index 0e06fd3cee4d..3b62aeeaa3a2 100644
--- a/arch/arm/boot/dts/kirkwood-cloudbox.dts
+++ b/arch/arm/boot/dts/kirkwood-cloudbox.dts
@@ -46,7 +46,7 @@
flash@0 {
#address-cells = <1>;
#size-cells = <1>;
- compatible = "mx25l4005a";
+ compatible = "mxicy,mx25l4005a";
reg = <0>;
spi-max-frequency = <20000000>;
mode = <0>;
diff --git a/arch/arm/boot/dts/kirkwood-dreamplug.dts b/arch/arm/boot/dts/kirkwood-dreamplug.dts
index ef3463e0ae19..28b3ee369778 100644
--- a/arch/arm/boot/dts/kirkwood-dreamplug.dts
+++ b/arch/arm/boot/dts/kirkwood-dreamplug.dts
@@ -43,7 +43,7 @@
m25p40@0 {
#address-cells = <1>;
#size-cells = <1>;
- compatible = "mx25l1606e";
+ compatible = "mxicy,mx25l1606e";
reg = <0>;
spi-max-frequency = <50000000>;
mode = <0>;
diff --git a/arch/arm/boot/dts/kirkwood-laplug.dts b/arch/arm/boot/dts/kirkwood-laplug.dts
index c9e82eff9bf2..6761ffa2c4ab 100644
--- a/arch/arm/boot/dts/kirkwood-laplug.dts
+++ b/arch/arm/boot/dts/kirkwood-laplug.dts
@@ -48,7 +48,7 @@
status = "okay";
eeprom@50 {
- compatible = "at,24c04";
+ compatible = "atmel,24c04";
pagesize = <16>;
reg = <0x50>;
};
diff --git a/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts b/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts
index 2cb0dc529165..b939f4f52d16 100644
--- a/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts
+++ b/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts
@@ -30,6 +30,16 @@
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 {
@@ -56,7 +66,7 @@
flash@0 {
#address-cells = <1>;
#size-cells = <1>;
- compatible = "mx25l12805d";
+ compatible = "mxicy,mx25l12805d";
reg = <0>;
spi-max-frequency = <50000000>;
mode = <0>;
@@ -73,14 +83,6 @@
ehci@50000 {
status = "okay";
};
-
- pcie-controller {
- status = "okay";
-
- pcie@1,0 {
- status = "okay";
- };
- };
};
gpio-leds {
diff --git a/arch/arm/boot/dts/kirkwood-ns2-common.dtsi b/arch/arm/boot/dts/kirkwood-ns2-common.dtsi
index 743152f31a81..e6e5ec4fe6b9 100644
--- a/arch/arm/boot/dts/kirkwood-ns2-common.dtsi
+++ b/arch/arm/boot/dts/kirkwood-ns2-common.dtsi
@@ -32,7 +32,7 @@
flash@0 {
#address-cells = <1>;
#size-cells = <1>;
- compatible = "mx25l4005a";
+ compatible = "mxicy,mx25l4005a";
reg = <0>;
spi-max-frequency = <20000000>;
mode = <0>;
@@ -50,7 +50,7 @@
status = "okay";
eeprom@50 {
- compatible = "at,24c04";
+ compatible = "atmel,24c04";
pagesize = <16>;
reg = <0x50>;
};
diff --git a/arch/arm/boot/dts/kirkwood-nsa310-common.dtsi b/arch/arm/boot/dts/kirkwood-nsa310-common.dtsi
index aa78c2d11fe7..e2cc85cc3b87 100644
--- a/arch/arm/boot/dts/kirkwood-nsa310-common.dtsi
+++ b/arch/arm/boot/dts/kirkwood-nsa310-common.dtsi
@@ -4,6 +4,16 @@
/ {
model = "ZyXEL NSA310";
+ mbus {
+ pcie-controller {
+ status = "okay";
+
+ pcie@1,0 {
+ status = "okay";
+ };
+ };
+ };
+
ocp@f1000000 {
pinctrl: pinctrl@10000 {
@@ -26,14 +36,6 @@
status = "okay";
nr-ports = <2>;
};
-
- pcie-controller {
- status = "okay";
-
- pcie@1,0 {
- status = "okay";
- };
- };
};
gpio_poweroff {
diff --git a/arch/arm/boot/dts/kirkwood-nsa310.dts b/arch/arm/boot/dts/kirkwood-nsa310.dts
index 03fa24cf3344..0a07af9d8e58 100644
--- a/arch/arm/boot/dts/kirkwood-nsa310.dts
+++ b/arch/arm/boot/dts/kirkwood-nsa310.dts
@@ -104,7 +104,7 @@
status = "okay";
adt7476: adt7476a@2e {
- compatible = "adt7476";
+ compatible = "adi,adt7476";
reg = <0x2e>;
};
};
diff --git a/arch/arm/boot/dts/kirkwood-nsa310a.dts b/arch/arm/boot/dts/kirkwood-nsa310a.dts
index a5e779452867..27ca6a79c48a 100644
--- a/arch/arm/boot/dts/kirkwood-nsa310a.dts
+++ b/arch/arm/boot/dts/kirkwood-nsa310a.dts
@@ -94,7 +94,7 @@
status = "okay";
lm85: lm85@2e {
- compatible = "lm85";
+ compatible = "national,lm85";
reg = <0x2e>;
};
};
diff --git a/arch/arm/boot/dts/kirkwood-openblocks_a6.dts b/arch/arm/boot/dts/kirkwood-openblocks_a6.dts
index b88da9392c32..0650beafc1de 100644
--- a/arch/arm/boot/dts/kirkwood-openblocks_a6.dts
+++ b/arch/arm/boot/dts/kirkwood-openblocks_a6.dts
@@ -40,7 +40,7 @@
pinctrl-names = "default";
s35390a: s35390a@30 {
- compatible = "s35390a";
+ compatible = "sii,s35390a";
reg = <0x30>;
};
};
diff --git a/arch/arm/boot/dts/kirkwood-openblocks_a7.dts b/arch/arm/boot/dts/kirkwood-openblocks_a7.dts
index b2f7cae06839..38520a287514 100644
--- a/arch/arm/boot/dts/kirkwood-openblocks_a7.dts
+++ b/arch/arm/boot/dts/kirkwood-openblocks_a7.dts
@@ -52,7 +52,7 @@
pinctrl-names = "default";
s24c02: s24c02@50 {
- compatible = "24c02";
+ compatible = "atmel,24c02";
reg = <0x50>;
};
};
diff --git a/arch/arm/boot/dts/kirkwood-t5325.dts b/arch/arm/boot/dts/kirkwood-t5325.dts
index 7d1c7677a18f..0bd70d928c69 100644
--- a/arch/arm/boot/dts/kirkwood-t5325.dts
+++ b/arch/arm/boot/dts/kirkwood-t5325.dts
@@ -127,11 +127,6 @@
i2c@11000 {
status = "okay";
-
- alc5621: alc5621@1a {
- compatible = "realtek,alc5621";
- reg = <0x1a>;
- };
};
serial@12000 {
diff --git a/arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi b/arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi
index f577b7df9a29..521c587acaee 100644
--- a/arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi
+++ b/arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi
@@ -24,11 +24,10 @@
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>;
@@ -36,12 +35,10 @@
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>;
diff --git a/arch/arm/boot/dts/omap2.dtsi b/arch/arm/boot/dts/omap2.dtsi
index 22f35ea142c1..8f8c07da4ac1 100644
--- a/arch/arm/boot/dts/omap2.dtsi
+++ b/arch/arm/boot/dts/omap2.dtsi
@@ -71,13 +71,6 @@
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;
diff --git a/arch/arm/boot/dts/omap2420.dtsi b/arch/arm/boot/dts/omap2420.dtsi
index 85b1fb014c43..2d9979835f24 100644
--- a/arch/arm/boot/dts/omap2420.dtsi
+++ b/arch/arm/boot/dts/omap2420.dtsi
@@ -125,6 +125,14 @@
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>;
diff --git a/arch/arm/boot/dts/omap2430.dtsi b/arch/arm/boot/dts/omap2430.dtsi
index d09697dab55e..42d2c61c9e2d 100644
--- a/arch/arm/boot/dts/omap2430.dtsi
+++ b/arch/arm/boot/dts/omap2430.dtsi
@@ -216,6 +216,13 @@
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>;
diff --git a/arch/arm/boot/dts/omap3-beagle-xm-ab.dts b/arch/arm/boot/dts/omap3-beagle-xm-ab.dts
new file mode 100644
index 000000000000..7ac3bcf59d59
--- /dev/null
+++ b/arch/arm/boot/dts/omap3-beagle-xm-ab.dts
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "omap3-beagle-xm.dts"
+
+/ {
+ /* HS USB Port 2 Power enable was inverted with the xM C */
+ hsusb2_power: hsusb2_power_reg {
+ enable-active-high;
+ };
+};
diff --git a/arch/arm/boot/dts/omap3-cm-t3x30.dtsi b/arch/arm/boot/dts/omap3-cm-t3x30.dtsi
index d00055809e31..25ba08331d88 100644
--- a/arch/arm/boot/dts/omap3-cm-t3x30.dtsi
+++ b/arch/arm/boot/dts/omap3-cm-t3x30.dtsi
@@ -10,18 +10,6 @@
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 {
@@ -35,58 +23,34 @@
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;
};
};
diff --git a/arch/arm/boot/dts/omap3-devkit8000.dts b/arch/arm/boot/dts/omap3-devkit8000.dts
index bf5a515a3247..da402f0fdab4 100644
--- a/arch/arm/boot/dts/omap3-devkit8000.dts
+++ b/arch/arm/boot/dts/omap3-devkit8000.dts
@@ -112,7 +112,6 @@
reg = <0 0 0>; /* CS0, offset 0 */
nand-bus-width = <16>;
- gpmc,device-nand;
gpmc,sync-clk-ps = <0>;
gpmc,cs-on-ns = <0>;
gpmc,cs-rd-off-ns = <44>;
diff --git a/arch/arm/boot/dts/omap3-igep.dtsi b/arch/arm/boot/dts/omap3-igep.dtsi
index b97736d98a64..e2d163bf0619 100644
--- a/arch/arm/boot/dts/omap3-igep.dtsi
+++ b/arch/arm/boot/dts/omap3-igep.dtsi
@@ -107,7 +107,7 @@
>;
};
- smsc911x_pins: pinmux_smsc911x_pins {
+ smsc9221_pins: pinmux_smsc9221_pins {
pinctrl-single,pins = <
0x1a2 (PIN_INPUT | MUX_MODE4) /* mcspi1_cs2.gpio_176 */
>;
diff --git a/arch/arm/boot/dts/omap3-igep0020.dts b/arch/arm/boot/dts/omap3-igep0020.dts
index 7abd64f6ae21..b22caaaf774b 100644
--- a/arch/arm/boot/dts/omap3-igep0020.dts
+++ b/arch/arm/boot/dts/omap3-igep0020.dts
@@ -10,7 +10,7 @@
*/
#include "omap3-igep.dtsi"
-#include "omap-gpmc-smsc911x.dtsi"
+#include "omap-gpmc-smsc9221.dtsi"
/ {
model = "IGEPv2 (TI OMAP AM/DM37x)";
@@ -248,7 +248,7 @@
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>;
diff --git a/arch/arm/boot/dts/omap3-lilly-a83x.dtsi b/arch/arm/boot/dts/omap3-lilly-a83x.dtsi
index 6369d9f43ca2..cc1dce6978f5 100644
--- a/arch/arm/boot/dts/omap3-lilly-a83x.dtsi
+++ b/arch/arm/boot/dts/omap3-lilly-a83x.dtsi
@@ -368,7 +368,6 @@
/* no elm on omap3 */
gpmc,mux-add-data = <0>;
- gpmc,device-nand;
gpmc,device-width = <2>;
gpmc,wait-pin = <0>;
gpmc,wait-monitoring-ns = <0>;
diff --git a/arch/arm/boot/dts/omap3-sb-t35.dtsi b/arch/arm/boot/dts/omap3-sb-t35.dtsi
index 7909c51b05a5..d59e3de1441e 100644
--- a/arch/arm/boot/dts/omap3-sb-t35.dtsi
+++ b/arch/arm/boot/dts/omap3-sb-t35.dtsi
@@ -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 = <
@@ -37,11 +23,10 @@
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>;
@@ -49,16 +34,14 @@
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;
};
diff --git a/arch/arm/boot/dts/omap3-sbc-t3517.dts b/arch/arm/boot/dts/omap3-sbc-t3517.dts
index 024c9c6c682d..42189b65d393 100644
--- a/arch/arm/boot/dts/omap3-sbc-t3517.dts
+++ b/arch/arm/boot/dts/omap3-sbc-t3517.dts
@@ -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 {
diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi
index 5e5790f631eb..4231191ade06 100644
--- a/arch/arm/boot/dts/omap3.dtsi
+++ b/arch/arm/boot/dts/omap3.dtsi
@@ -61,7 +61,7 @@
ti,hwmods = "mpu";
};
- iva {
+ iva: iva {
compatible = "ti,iva2.2";
ti,hwmods = "iva";
@@ -74,7 +74,7 @@
/*
* XXX: Use a flat representation of the OMAP3 interconnect.
* The real OMAP interconnect network is quite complex.
- * Since that will not bring real advantage to represent that in DT for
+ * Since it will not bring real advantage to represent that in DT for
* the moment, just use a fake OCP bus entry to represent the whole bus
* hierarchy.
*/
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
index 27fcac874742..649b5cd38b40 100644
--- a/arch/arm/boot/dts/omap4.dtsi
+++ b/arch/arm/boot/dts/omap4.dtsi
@@ -72,7 +72,7 @@
};
/*
- * The soc node represents the soc top level view. It is uses for IPs
+ * The soc node represents the soc top level view. It is used for IPs
* that are not memory mapped in the MPU view or for the MPU itself.
*/
soc {
@@ -96,7 +96,7 @@
/*
* XXX: Use a flat representation of the OMAP4 interconnect.
* The real OMAP interconnect network is quite complex.
- * Since that will not bring real advantage to represent that in DT for
+ * Since it will not bring real advantage to represent that in DT for
* the moment, just use a fake OCP bus entry to represent the whole bus
* hierarchy.
*/
diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
index 6f3de22fb266..36b4312a5e0d 100644
--- a/arch/arm/boot/dts/omap5.dtsi
+++ b/arch/arm/boot/dts/omap5.dtsi
@@ -93,7 +93,7 @@
};
/*
- * The soc node represents the soc top level view. It is uses for IPs
+ * The soc node represents the soc top level view. It is used for IPs
* that are not memory mapped in the MPU view or for the MPU itself.
*/
soc {
@@ -107,7 +107,7 @@
/*
* XXX: Use a flat representation of the OMAP3 interconnect.
* The real OMAP interconnect network is quite complex.
- * Since that will not bring real advantage to represent that in DT for
+ * Since it will not bring real advantage to represent that in DT for
* the moment, just use a fake OCP bus entry to represent the whole bus
* hierarchy.
*/
@@ -630,6 +630,13 @@
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>;
@@ -813,6 +820,12 @@
<0x4a084c00 0x40>;
reg-names = "phy_rx", "phy_tx", "pll_ctrl";
ctrl-module = <&omap_control_usb3phy>;
+ clocks = <&usb_phy_cm_clk32k>,
+ <&sys_clkin>,
+ <&usb_otg_ss_refclk960m>;
+ clock-names = "wkupclk",
+ "sysclk",
+ "refclk";
#phy-cells = <0>;
};
};
diff --git a/arch/arm/boot/dts/r8a7740.dtsi b/arch/arm/boot/dts/r8a7740.dtsi
index 8280884bfa59..2551e9438d35 100644
--- a/arch/arm/boot/dts/r8a7740.dtsi
+++ b/arch/arm/boot/dts/r8a7740.dtsi
@@ -28,7 +28,6 @@
gic: interrupt-controller@c2800000 {
compatible = "arm,cortex-a9-gic";
#interrupt-cells = <3>;
- #address-cells = <1>;
interrupt-controller;
reg = <0xc2800000 0x1000>,
<0xc2000000 0x1000>;
diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts
index 6e99eb2df076..d01048ab3e77 100644
--- a/arch/arm/boot/dts/r8a7790-lager.dts
+++ b/arch/arm/boot/dts/r8a7790-lager.dts
@@ -141,12 +141,12 @@
};
sdhi0_pins: sd0 {
- renesas,gpios = "sdhi0_data4", "sdhi0_ctrl";
+ renesas,groups = "sdhi0_data4", "sdhi0_ctrl";
renesas,function = "sdhi0";
};
sdhi2_pins: sd2 {
- renesas,gpios = "sdhi2_data4", "sdhi2_ctrl";
+ renesas,groups = "sdhi2_data4", "sdhi2_ctrl";
renesas,function = "sdhi2";
};
diff --git a/arch/arm/boot/dts/r8a7791-koelsch.dts b/arch/arm/boot/dts/r8a7791-koelsch.dts
index bdd73e6657b2..de1b6977c69a 100644
--- a/arch/arm/boot/dts/r8a7791-koelsch.dts
+++ b/arch/arm/boot/dts/r8a7791-koelsch.dts
@@ -230,17 +230,17 @@
};
sdhi0_pins: sd0 {
- renesas,gpios = "sdhi0_data4", "sdhi0_ctrl";
+ renesas,groups = "sdhi0_data4", "sdhi0_ctrl";
renesas,function = "sdhi0";
};
sdhi1_pins: sd1 {
- renesas,gpios = "sdhi1_data4", "sdhi1_ctrl";
+ renesas,groups = "sdhi1_data4", "sdhi1_ctrl";
renesas,function = "sdhi1";
};
sdhi2_pins: sd2 {
- renesas,gpios = "sdhi2_data4", "sdhi2_ctrl";
+ renesas,groups = "sdhi2_data4", "sdhi2_ctrl";
renesas,function = "sdhi2";
};
diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi
index bb36596ea205..ed9a70af3e3f 100644
--- a/arch/arm/boot/dts/rk3188.dtsi
+++ b/arch/arm/boot/dts/rk3188.dtsi
@@ -149,7 +149,7 @@
uart0 {
uart0_xfer: uart0-xfer {
- rockchip,pins = <RK_GPIO1 0 RK_FUNC_1 &pcfg_pull_none>,
+ rockchip,pins = <RK_GPIO1 0 RK_FUNC_1 &pcfg_pull_up>,
<RK_GPIO1 1 RK_FUNC_1 &pcfg_pull_none>;
};
@@ -164,7 +164,7 @@
uart1 {
uart1_xfer: uart1-xfer {
- rockchip,pins = <RK_GPIO1 4 RK_FUNC_1 &pcfg_pull_none>,
+ rockchip,pins = <RK_GPIO1 4 RK_FUNC_1 &pcfg_pull_up>,
<RK_GPIO1 5 RK_FUNC_1 &pcfg_pull_none>;
};
@@ -179,7 +179,7 @@
uart2 {
uart2_xfer: uart2-xfer {
- rockchip,pins = <RK_GPIO1 8 RK_FUNC_1 &pcfg_pull_none>,
+ rockchip,pins = <RK_GPIO1 8 RK_FUNC_1 &pcfg_pull_up>,
<RK_GPIO1 9 RK_FUNC_1 &pcfg_pull_none>;
};
/* no rts / cts for uart2 */
@@ -187,7 +187,7 @@
uart3 {
uart3_xfer: uart3-xfer {
- rockchip,pins = <RK_GPIO1 10 RK_FUNC_1 &pcfg_pull_none>,
+ rockchip,pins = <RK_GPIO1 10 RK_FUNC_1 &pcfg_pull_up>,
<RK_GPIO1 11 RK_FUNC_1 &pcfg_pull_none>;
};
diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/sama5d3.dtsi
index eabcfdbb403a..a106b0872910 100644
--- a/arch/arm/boot/dts/sama5d3.dtsi
+++ b/arch/arm/boot/dts/sama5d3.dtsi
@@ -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";
diff --git a/arch/arm/boot/dts/sama5d3_mci2.dtsi b/arch/arm/boot/dts/sama5d3_mci2.dtsi
index b029fe7ef17a..1b02208ea6ff 100644
--- a/arch/arm/boot/dts/sama5d3_mci2.dtsi
+++ b/arch/arm/boot/dts/sama5d3_mci2.dtsi
@@ -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 {
diff --git a/arch/arm/boot/dts/sama5d3_tcb1.dtsi b/arch/arm/boot/dts/sama5d3_tcb1.dtsi
index 382b04431f66..02848453ca0c 100644
--- a/arch/arm/boot/dts/sama5d3_tcb1.dtsi
+++ b/arch/arm/boot/dts/sama5d3_tcb1.dtsi
@@ -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 {
diff --git a/arch/arm/boot/dts/sama5d3_uart.dtsi b/arch/arm/boot/dts/sama5d3_uart.dtsi
index a9fa75e41652..7a8d4c6115f7 100644
--- a/arch/arm/boot/dts/sama5d3_uart.dtsi
+++ b/arch/arm/boot/dts/sama5d3_uart.dtsi
@@ -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 {
diff --git a/arch/arm/boot/dts/sh73a0.dtsi b/arch/arm/boot/dts/sh73a0.dtsi
index b7bd3b9a6753..5ecf552e1c00 100644
--- a/arch/arm/boot/dts/sh73a0.dtsi
+++ b/arch/arm/boot/dts/sh73a0.dtsi
@@ -34,7 +34,6 @@
gic: interrupt-controller@f0001000 {
compatible = "arm,cortex-a9-gic";
#interrupt-cells = <3>;
- #address-cells = <1>;
interrupt-controller;
reg = <0xf0001000 0x1000>,
<0xf0000100 0x100>;
diff --git a/arch/arm/boot/dts/spear320-hmi.dts b/arch/arm/boot/dts/spear320-hmi.dts
index 3075d2d3a8be..0aa6fef5ce22 100644
--- a/arch/arm/boot/dts/spear320-hmi.dts
+++ b/arch/arm/boot/dts/spear320-hmi.dts
@@ -1,7 +1,7 @@
/*
* DTS file for SPEAr320 Evaluation Baord
*
- * Copyright 2012 Shiraz Hashim <shiraz.hashim@st.com>
+ * Copyright 2012 Shiraz Hashim <shiraz.linux.kernel@gmail.com>
*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
diff --git a/arch/arm/boot/dts/ste-ccu8540.dts b/arch/arm/boot/dts/ste-ccu8540.dts
index 7f3baf51a3a9..32dd55e5f4e6 100644
--- a/arch/arm/boot/dts/ste-ccu8540.dts
+++ b/arch/arm/boot/dts/ste-ccu8540.dts
@@ -18,6 +18,7 @@
compatible = "st-ericsson,ccu8540", "st-ericsson,u8540";
memory@0 {
+ device_type = "memory";
reg = <0x20000000 0x1f000000>, <0xc0000000 0x3f000000>;
};
diff --git a/arch/arm/boot/dts/ste-ccu9540.dts b/arch/arm/boot/dts/ste-ccu9540.dts
index 229508750890..651c56d400a4 100644
--- a/arch/arm/boot/dts/ste-ccu9540.dts
+++ b/arch/arm/boot/dts/ste-ccu9540.dts
@@ -38,8 +38,8 @@
arm,primecell-periphid = <0x10480180>;
max-frequency = <100000000>;
bus-width = <4>;
- mmc-cap-sd-highspeed;
- mmc-cap-mmc-highspeed;
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
vmmc-supply = <&ab8500_ldo_aux3_reg>;
cd-gpios = <&gpio7 6 0x4>; // 230
@@ -63,7 +63,7 @@
arm,primecell-periphid = <0x10480180>;
max-frequency = <100000000>;
bus-width = <8>;
- mmc-cap-mmc-highspeed;
+ cap-mmc-highspeed;
vmmc-supply = <&ab8500_ldo_aux2_reg>;
status = "okay";
diff --git a/arch/arm/boot/dts/ste-href.dtsi b/arch/arm/boot/dts/ste-href.dtsi
index 6cb9b68e2188..bf8f0eddc2c0 100644
--- a/arch/arm/boot/dts/ste-href.dtsi
+++ b/arch/arm/boot/dts/ste-href.dtsi
@@ -116,8 +116,15 @@
arm,primecell-periphid = <0x10480180>;
max-frequency = <100000000>;
bus-width = <4>;
- mmc-cap-sd-highspeed;
- mmc-cap-mmc-highspeed;
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ sd-uhs-sdr12;
+ sd-uhs-sdr25;
+ full-pwr-cycle;
+ st,sig-dir-dat0;
+ st,sig-dir-dat2;
+ st,sig-dir-cmd;
+ st,sig-pin-fbclk;
vmmc-supply = <&ab8500_ldo_aux3_reg>;
vqmmc-supply = <&vmmci>;
pinctrl-names = "default", "sleep";
@@ -132,6 +139,7 @@
arm,primecell-periphid = <0x10480180>;
max-frequency = <100000000>;
bus-width = <4>;
+ non-removable;
pinctrl-names = "default", "sleep";
pinctrl-0 = <&sdi1_default_mode>;
pinctrl-1 = <&sdi1_sleep_mode>;
@@ -144,7 +152,9 @@
arm,primecell-periphid = <0x10480180>;
max-frequency = <100000000>;
bus-width = <8>;
- mmc-cap-mmc-highspeed;
+ cap-mmc-highspeed;
+ non-removable;
+ vmmc-supply = <&db8500_vsmps2_reg>;
pinctrl-names = "default", "sleep";
pinctrl-0 = <&sdi2_default_mode>;
pinctrl-1 = <&sdi2_sleep_mode>;
@@ -157,7 +167,8 @@
arm,primecell-periphid = <0x10480180>;
max-frequency = <100000000>;
bus-width = <8>;
- mmc-cap-mmc-highspeed;
+ cap-mmc-highspeed;
+ non-removable;
vmmc-supply = <&ab8500_ldo_aux2_reg>;
pinctrl-names = "default", "sleep";
pinctrl-0 = <&sdi4_default_mode>;
diff --git a/arch/arm/boot/dts/ste-nomadik-stn8815.dtsi b/arch/arm/boot/dts/ste-nomadik-stn8815.dtsi
index 5acc0449676a..d316c955bd5f 100644
--- a/arch/arm/boot/dts/ste-nomadik-stn8815.dtsi
+++ b/arch/arm/boot/dts/ste-nomadik-stn8815.dtsi
@@ -840,8 +840,8 @@
interrupts = <22>;
max-frequency = <48000000>;
bus-width = <4>;
- mmc-cap-mmc-highspeed;
- mmc-cap-sd-highspeed;
+ cap-mmc-highspeed;
+ cap-sd-highspeed;
cd-gpios = <&gpio3 15 0x1>;
cd-inverted;
pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/ste-snowball.dts b/arch/arm/boot/dts/ste-snowball.dts
index a2f632d0be2a..474ef83229cd 100644
--- a/arch/arm/boot/dts/ste-snowball.dts
+++ b/arch/arm/boot/dts/ste-snowball.dts
@@ -156,7 +156,7 @@
arm,primecell-periphid = <0x10480180>;
max-frequency = <100000000>;
bus-width = <4>;
- mmc-cap-mmc-highspeed;
+ cap-mmc-highspeed;
vmmc-supply = <&ab8500_ldo_aux3_reg>;
vqmmc-supply = <&vmmci>;
pinctrl-names = "default", "sleep";
@@ -195,7 +195,7 @@
arm,primecell-periphid = <0x10480180>;
max-frequency = <100000000>;
bus-width = <8>;
- mmc-cap-mmc-highspeed;
+ cap-mmc-highspeed;
vmmc-supply = <&ab8500_ldo_aux2_reg>;
pinctrl-names = "default", "sleep";
pinctrl-0 = <&sdi4_default_mode>;
diff --git a/arch/arm/boot/dts/ste-u300.dts b/arch/arm/boot/dts/ste-u300.dts
index 6fe688e9e4da..82a661677e97 100644
--- a/arch/arm/boot/dts/ste-u300.dts
+++ b/arch/arm/boot/dts/ste-u300.dts
@@ -442,8 +442,8 @@
clock-names = "apb_pclk", "mclk";
max-frequency = <24000000>;
bus-width = <4>; // SD-card slot
- mmc-cap-mmc-highspeed;
- mmc-cap-sd-highspeed;
+ cap-mmc-highspeed;
+ cap-sd-highspeed;
cd-gpios = <&gpio 12 0x4>;
cd-inverted;
vmmc-supply = <&ab3100_ldo_g_reg>;
diff --git a/arch/arm/boot/dts/stih415-pinctrl.dtsi b/arch/arm/boot/dts/stih415-pinctrl.dtsi
index f09fb10a3791..81df870e5ee6 100644
--- a/arch/arm/boot/dts/stih415-pinctrl.dtsi
+++ b/arch/arm/boot/dts/stih415-pinctrl.dtsi
@@ -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 {
@@ -187,7 +187,7 @@
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 {
@@ -282,7 +282,7 @@
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 {
@@ -423,7 +423,7 @@
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 {
@@ -460,7 +460,7 @@
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 {
diff --git a/arch/arm/boot/dts/stih416-pinctrl.dtsi b/arch/arm/boot/dts/stih416-pinctrl.dtsi
index aeea304086eb..250d5ecc951e 100644
--- a/arch/arm/boot/dts/stih416-pinctrl.dtsi
+++ b/arch/arm/boot/dts/stih416-pinctrl.dtsi
@@ -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 {
@@ -201,7 +201,7 @@
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 {
@@ -333,7 +333,7 @@
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 {
@@ -461,7 +461,7 @@
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 {
@@ -498,7 +498,7 @@
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 {
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index 32efc105df83..aba1c8a3f388 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -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";
@@ -109,6 +109,14 @@
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";
@@ -805,9 +813,9 @@
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>;
diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi
index cf45a1a39483..6d540a025148 100644
--- a/arch/arm/boot/dts/tegra124.dtsi
+++ b/arch/arm/boot/dts/tegra124.dtsi
@@ -233,19 +233,6 @@
status = "disabled";
};
- serial@0,70006400 {
- compatible = "nvidia,tegra124-uart", "nvidia,tegra20-uart";
- reg = <0x0 0x70006400 0x0 0x40>;
- reg-shift = <2>;
- interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&tegra_car TEGRA124_CLK_UARTE>;
- resets = <&tegra_car 66>;
- reset-names = "serial";
- dmas = <&apbdma 20>, <&apbdma 20>;
- dma-names = "rx", "tx";
- status = "disabled";
- };
-
pwm@0,7000a000 {
compatible = "nvidia,tegra124-pwm", "nvidia,tegra20-pwm";
reg = <0x0 0x7000a000 0x0 0x100>;
diff --git a/arch/arm/boot/dts/vf610-twr.dts b/arch/arm/boot/dts/vf610-twr.dts
index 7dd1d6ede525..ded361075aab 100644
--- a/arch/arm/boot/dts/vf610-twr.dts
+++ b/arch/arm/boot/dts/vf610-twr.dts
@@ -25,11 +25,13 @@
clocks {
audio_ext {
compatible = "fixed-clock";
+ #clock-cells = <0>;
clock-frequency = <24576000>;
};
enet_ext {
compatible = "fixed-clock";
+ #clock-cells = <0>;
clock-frequency = <50000000>;
};
};
diff --git a/arch/arm/boot/dts/vf610.dtsi b/arch/arm/boot/dts/vf610.dtsi
index 804873367669..b8ce0aa7b157 100644
--- a/arch/arm/boot/dts/vf610.dtsi
+++ b/arch/arm/boot/dts/vf610.dtsi
@@ -45,11 +45,13 @@
sxosc {
compatible = "fixed-clock";
+ #clock-cells = <0>;
clock-frequency = <32768>;
};
fxosc {
compatible = "fixed-clock";
+ #clock-cells = <0>;
clock-frequency = <24000000>;
};
};
@@ -72,8 +74,6 @@
intc: interrupt-controller@40002000 {
compatible = "arm,cortex-a9-gic";
#interrupt-cells = <3>;
- #address-cells = <1>;
- #size-cells = <1>;
interrupt-controller;
reg = <0x40003000 0x1000>,
<0x40002100 0x100>;
diff --git a/arch/arm/boot/dts/zynq-7000.dtsi b/arch/arm/boot/dts/zynq-7000.dtsi
index 511180769af5..c1176abc34d9 100644
--- a/arch/arm/boot/dts/zynq-7000.dtsi
+++ b/arch/arm/boot/dts/zynq-7000.dtsi
@@ -24,6 +24,7 @@
device_type = "cpu";
reg = <0>;
clocks = <&clkc 3>;
+ clock-latency = <1000>;
operating-points = <
/* kHz uV */
666667 1000000
@@ -54,6 +55,28 @@
interrupt-parent = <&intc>;
ranges;
+ i2c0: zynq-i2c@e0004000 {
+ compatible = "cdns,i2c-r1p10";
+ status = "disabled";
+ clocks = <&clkc 38>;
+ interrupt-parent = <&intc>;
+ interrupts = <0 25 4>;
+ reg = <0xe0004000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c1: zynq-i2c@e0005000 {
+ compatible = "cdns,i2c-r1p10";
+ status = "disabled";
+ clocks = <&clkc 39>;
+ interrupt-parent = <&intc>;
+ interrupts = <0 48 4>;
+ reg = <0xe0005000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
intc: interrupt-controller@f8f01000 {
compatible = "arm,cortex-a9-gic";
#interrupt-cells = <3>;
diff --git a/arch/arm/boot/dts/zynq-zc702.dts b/arch/arm/boot/dts/zynq-zc702.dts
index c913f77a21eb..5e09cee33d42 100644
--- a/arch/arm/boot/dts/zynq-zc702.dts
+++ b/arch/arm/boot/dts/zynq-zc702.dts
@@ -34,6 +34,82 @@
phy-mode = "rgmii";
};
+&i2c0 {
+ status = "okay";
+ clock-frequency = <400000>;
+
+ i2cswitch@74 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x74>;
+
+ i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ si570: clock-generator@5d {
+ #clock-cells = <0>;
+ compatible = "silabs,si570";
+ temperature-stability = <50>;
+ reg = <0x5d>;
+ factory-fout = <156250000>;
+ clock-frequency = <148500000>;
+ };
+ };
+
+ i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ eeprom@54 {
+ compatible = "at,24c08";
+ reg = <0x54>;
+ };
+ };
+
+ i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ gpio@21 {
+ compatible = "ti,tca6416";
+ reg = <0x21>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+ };
+
+ i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ rtc@51 {
+ compatible = "nxp,pcf8563";
+ reg = <0x51>;
+ };
+ };
+
+ i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ hwmon@52 {
+ compatible = "ti,ucd9248";
+ reg = <52>;
+ };
+ hwmon@53 {
+ compatible = "ti,ucd9248";
+ reg = <53>;
+ };
+ hwmon@54 {
+ compatible = "ti,ucd9248";
+ reg = <54>;
+ };
+ };
+ };
+};
+
&sdhci0 {
status = "okay";
};
diff --git a/arch/arm/boot/dts/zynq-zc706.dts b/arch/arm/boot/dts/zynq-zc706.dts
index 88f62c50382e..4cc9913078cd 100644
--- a/arch/arm/boot/dts/zynq-zc706.dts
+++ b/arch/arm/boot/dts/zynq-zc706.dts
@@ -35,6 +35,74 @@
phy-mode = "rgmii";
};
+&i2c0 {
+ status = "okay";
+ clock-frequency = <400000>;
+
+ i2cswitch@74 {
+ compatible = "nxp,pca9548";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x74>;
+
+ i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ si570: clock-generator@5d {
+ #clock-cells = <0>;
+ compatible = "silabs,si570";
+ temperature-stability = <50>;
+ reg = <0x5d>;
+ factory-fout = <156250000>;
+ clock-frequency = <148500000>;
+ };
+ };
+
+ i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ eeprom@54 {
+ compatible = "at,24c08";
+ reg = <0x54>;
+ };
+ };
+
+ i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ gpio@21 {
+ compatible = "ti,tca6416";
+ reg = <0x21>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+ };
+
+ i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ rtc@51 {
+ compatible = "nxp,pcf8563";
+ reg = <0x51>;
+ };
+ };
+
+ i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ ucd90120@65 {
+ compatible = "ti,ucd90120";
+ reg = <0x65>;
+ };
+ };
+ };
+};
+
&sdhci0 {
status = "okay";
};
diff --git a/arch/arm/common/bL_switcher.c b/arch/arm/common/bL_switcher.c
index 5774b6ea7ad5..490f3dced749 100644
--- a/arch/arm/common/bL_switcher.c
+++ b/arch/arm/common/bL_switcher.c
@@ -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;
@@ -797,10 +801,8 @@ static int __init bL_switcher_init(void)
{
int ret;
- if (MAX_NR_CLUSTERS != 2) {
- pr_err("%s: only dual cluster systems are supported\n", __func__);
- return -EINVAL;
- }
+ if (!mcpm_is_available())
+ return -ENODEV;
cpu_notifier(bL_switcher_hotplug_callback, 0);
diff --git a/arch/arm/common/edma.c b/arch/arm/common/edma.c
index 41bca32409fc..5339009b3c0c 100644
--- a/arch/arm/common/edma.c
+++ b/arch/arm/common/edma.c
@@ -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;
}
diff --git a/arch/arm/common/mcpm_entry.c b/arch/arm/common/mcpm_entry.c
index 1e361abc29eb..86fd60fefbc9 100644
--- a/arch/arm/common/mcpm_entry.c
+++ b/arch/arm/common/mcpm_entry.c
@@ -48,6 +48,11 @@ int __init mcpm_platform_register(const struct mcpm_platform_ops *ops)
return 0;
}
+bool mcpm_is_available(void)
+{
+ return (platform_ops) ? true : false;
+}
+
int mcpm_cpu_power_up(unsigned int cpu, unsigned int cluster)
{
if (!platform_ops)
diff --git a/arch/arm/configs/bcm_defconfig b/arch/arm/configs/bcm_defconfig
index 01004640ee4d..3df3f3a79ef4 100644
--- a/arch/arm/configs/bcm_defconfig
+++ b/arch/arm/configs/bcm_defconfig
@@ -132,7 +132,7 @@ CONFIG_CRC_ITU_T=y
CONFIG_CRC7=y
CONFIG_XZ_DEC=y
CONFIG_AVERAGE=y
-CONFIG_PINCTRL_CAPRI=y
+CONFIG_PINCTRL_BCM281XX=y
CONFIG_WATCHDOG=y
CONFIG_BCM_KONA_WDT=y
CONFIG_BCM_KONA_WDT_DEBUG=y
diff --git a/arch/arm/configs/exynos_defconfig b/arch/arm/configs/exynos_defconfig
index 4ce7b70ea901..e07a227ec0db 100644
--- a/arch/arm/configs/exynos_defconfig
+++ b/arch/arm/configs/exynos_defconfig
@@ -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
diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig
index a9667957b757..a4e8d017f25b 100644
--- a/arch/arm/configs/omap2plus_defconfig
+++ b/arch/arm/configs/omap2plus_defconfig
@@ -226,7 +226,7 @@ CONFIG_USB_DWC3=m
CONFIG_USB_TEST=y
CONFIG_NOP_USB_XCEIV=y
CONFIG_OMAP_USB2=y
-CONFIG_OMAP_USB3=y
+CONFIG_TI_PIPE3=y
CONFIG_AM335X_PHY_USB=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_DEBUG=y
diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig
index b5df4a511b0a..81ba78eaf54a 100644
--- a/arch/arm/configs/sunxi_defconfig
+++ b/arch/arm/configs/sunxi_defconfig
@@ -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
diff --git a/arch/arm/configs/u300_defconfig b/arch/arm/configs/u300_defconfig
index fd81a1b99cce..aaa95ab606a8 100644
--- a/arch/arm/configs/u300_defconfig
+++ b/arch/arm/configs/u300_defconfig
@@ -11,6 +11,7 @@ CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_LBDAF is not set
# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
# CONFIG_IOSCHED_CFQ is not set
# CONFIG_ARCH_MULTI_V7 is not set
CONFIG_ARCH_U300=y
@@ -21,7 +22,6 @@ CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_CMDLINE="root=/dev/ram0 rw rootfstype=rootfs console=ttyAMA0,115200n8 lpj=515072"
CONFIG_CPU_IDLE=y
-CONFIG_FPE_NWFPE=y
# CONFIG_SUSPEND is not set
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
@@ -64,8 +64,8 @@ CONFIG_TMPFS=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_FS=y
# CONFIG_SCHED_DEBUG is not set
CONFIG_TIMER_STATS=y
# CONFIG_DEBUG_PREEMPT is not set
-CONFIG_DEBUG_INFO=y
diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig
index 65f77885c167..d219d6a43238 100644
--- a/arch/arm/configs/u8500_defconfig
+++ b/arch/arm/configs/u8500_defconfig
@@ -1,16 +1,16 @@
# CONFIG_SWAP is not set
CONFIG_SYSVIPC=y
-CONFIG_NO_HZ=y
+CONFIG_NO_HZ_IDLE=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_KALLSYMS_ALL=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
CONFIG_ARCH_U8500=y
CONFIG_MACH_HREFV60=y
CONFIG_MACH_SNOWBALL=y
-CONFIG_MACH_UX500_DT=y
CONFIG_SMP=y
CONFIG_NR_CPUS=2
CONFIG_PREEMPT=y
@@ -34,16 +34,22 @@ CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_NETFILTER=y
CONFIG_PHONET=y
-# CONFIG_WIRELESS is not set
+CONFIG_CFG80211=y
+CONFIG_CFG80211_DEBUGFS=y
+CONFIG_MAC80211=y
+CONFIG_MAC80211_LEDS=y
CONFIG_CAIF=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=65536
CONFIG_SENSORS_BH1780=y
CONFIG_NETDEVICES=y
CONFIG_SMSC911X=y
CONFIG_SMSC_PHY=y
-# CONFIG_WLAN is not set
+CONFIG_CW1200=y
+CONFIG_CW1200_WLAN_SDIO=y
# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
CONFIG_INPUT_EVDEV=y
# CONFIG_KEYBOARD_ATKBD is not set
@@ -85,15 +91,12 @@ CONFIG_AB8500_USB=y
CONFIG_USB_GADGET=y
CONFIG_USB_ETH=m
CONFIG_MMC=y
-CONFIG_MMC_UNSAFE_RESUME=y
-# CONFIG_MMC_BLOCK_BOUNCE is not set
CONFIG_MMC_ARMMMCI=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_LM3530=y
CONFIG_LEDS_GPIO=y
CONFIG_LEDS_LP5521=y
-CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_AB8500=y
@@ -103,6 +106,11 @@ CONFIG_STE_DMA40=y
CONFIG_STAGING=y
CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
CONFIG_HSEM_U8500=y
+CONFIG_IIO=y
+CONFIG_IIO_ST_ACCEL_3AXIS=y
+CONFIG_IIO_ST_GYRO_3AXIS=y
+CONFIG_IIO_ST_MAGN_3AXIS=y
+CONFIG_IIO_ST_PRESS=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y
@@ -110,8 +118,6 @@ CONFIG_EXT2_FS_SECURITY=y
CONFIG_EXT3_FS=y
CONFIG_EXT4_FS=y
CONFIG_VFAT_FS=y
-CONFIG_DEVTMPFS=y
-CONFIG_DEVTMPFS_MOUNT=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
# CONFIG_MISC_FILESYSTEMS is not set
diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
index c651e3b26ec7..4764344367d4 100644
--- a/arch/arm/include/asm/cputype.h
+++ b/arch/arm/include/asm/cputype.h
@@ -222,22 +222,22 @@ static inline int cpu_is_xsc3(void)
#endif
/*
- * Marvell's PJ4 core is based on V7 version. It has some modification
- * for coprocessor setting. For this reason, we need a way to distinguish
- * it.
+ * Marvell's PJ4 and PJ4B cores are based on V7 version,
+ * but require a specical sequence for enabling coprocessors.
+ * For this reason, we need a way to distinguish them.
*/
-#ifndef CONFIG_CPU_PJ4
-#define cpu_is_pj4() 0
-#else
+#if defined(CONFIG_CPU_PJ4) || defined(CONFIG_CPU_PJ4B)
static inline int cpu_is_pj4(void)
{
unsigned int id;
id = read_cpuid_id();
- if ((id & 0xfffffff0) == 0x562f5840)
+ if ((id & 0xff0fff00) == 0x560f5800)
return 1;
return 0;
}
+#else
+#define cpu_is_pj4() 0
#endif
#endif
diff --git a/arch/arm/include/asm/div64.h b/arch/arm/include/asm/div64.h
index 191ada6e4d2d..662c7bd06108 100644
--- a/arch/arm/include/asm/div64.h
+++ b/arch/arm/include/asm/div64.h
@@ -156,7 +156,7 @@
/* Select the best insn combination to perform the */ \
/* actual __m * __n / (__p << 64) operation. */ \
if (!__c) { \
- asm ( "umull %Q0, %R0, %1, %Q2\n\t" \
+ asm ( "umull %Q0, %R0, %Q1, %Q2\n\t" \
"mov %Q0, #0" \
: "=&r" (__res) \
: "r" (__m), "r" (__n) \
diff --git a/arch/arm/include/asm/mcpm.h b/arch/arm/include/asm/mcpm.h
index 608516ebabfe..a5ff410dcdb6 100644
--- a/arch/arm/include/asm/mcpm.h
+++ b/arch/arm/include/asm/mcpm.h
@@ -54,6 +54,13 @@ void mcpm_set_early_poke(unsigned cpu, unsigned cluster,
*/
/**
+ * mcpm_is_available - returns whether MCPM is initialized and available
+ *
+ * This returns true or false accordingly.
+ */
+bool mcpm_is_available(void);
+
+/**
* mcpm_cpu_power_up - make given CPU in given cluster runable
*
* @cpu: CPU number within given cluster
diff --git a/arch/arm/include/asm/tlb.h b/arch/arm/include/asm/tlb.h
index 0baf7f0d9394..f1a0dace3efe 100644
--- a/arch/arm/include/asm/tlb.h
+++ b/arch/arm/include/asm/tlb.h
@@ -98,15 +98,25 @@ static inline void __tlb_alloc_page(struct mmu_gather *tlb)
}
}
-static inline void tlb_flush_mmu(struct mmu_gather *tlb)
+static inline void tlb_flush_mmu_tlbonly(struct mmu_gather *tlb)
{
tlb_flush(tlb);
+}
+
+static inline void tlb_flush_mmu_free(struct mmu_gather *tlb)
+{
free_pages_and_swap_cache(tlb->pages, tlb->nr);
tlb->nr = 0;
if (tlb->pages == tlb->local)
__tlb_alloc_page(tlb);
}
+static inline void tlb_flush_mmu(struct mmu_gather *tlb)
+{
+ tlb_flush_mmu_tlbonly(tlb);
+ tlb_flush_mmu_free(tlb);
+}
+
static inline void
tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end)
{
diff --git a/arch/arm/include/asm/trusted_foundations.h b/arch/arm/include/asm/trusted_foundations.h
index b5f7705abcb0..624e1d436c6c 100644
--- a/arch/arm/include/asm/trusted_foundations.h
+++ b/arch/arm/include/asm/trusted_foundations.h
@@ -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);
}
diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h
index 12c3a5decc60..75d95799b6e6 100644
--- a/arch/arm/include/asm/uaccess.h
+++ b/arch/arm/include/asm/uaccess.h
@@ -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))) { \
diff --git a/arch/arm/include/asm/xen/hypercall.h b/arch/arm/include/asm/xen/hypercall.h
index 7704e28c3483..712b50e0a6dc 100644
--- a/arch/arm/include/asm/xen/hypercall.h
+++ b/arch/arm/include/asm/xen/hypercall.h
@@ -34,6 +34,7 @@
#define _ASM_ARM_XEN_HYPERCALL_H
#include <xen/interface/xen.h>
+#include <xen/interface/sched.h>
long privcmd_call(unsigned call, unsigned long a1,
unsigned long a2, unsigned long a3,
@@ -48,6 +49,16 @@ int HYPERVISOR_memory_op(unsigned int cmd, void *arg);
int HYPERVISOR_physdev_op(int cmd, void *arg);
int HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args);
int HYPERVISOR_tmem_op(void *arg);
+int HYPERVISOR_multicall(struct multicall_entry *calls, uint32_t nr);
+
+static inline int
+HYPERVISOR_suspend(unsigned long start_info_mfn)
+{
+ struct sched_shutdown r = { .reason = SHUTDOWN_suspend };
+
+ /* start_info_mfn is unused on ARM */
+ return HYPERVISOR_sched_op(SCHEDOP_shutdown, &r);
+}
static inline void
MULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va,
@@ -63,9 +74,4 @@ MULTI_mmu_update(struct multicall_entry *mcl, struct mmu_update *req,
BUG();
}
-static inline int
-HYPERVISOR_multicall(void *call_list, int nr_calls)
-{
- BUG();
-}
#endif /* _ASM_ARM_XEN_HYPERCALL_H */
diff --git a/arch/arm/include/asm/xen/interface.h b/arch/arm/include/asm/xen/interface.h
index 1151188bcd83..50066006e6bd 100644
--- a/arch/arm/include/asm/xen/interface.h
+++ b/arch/arm/include/asm/xen/interface.h
@@ -40,6 +40,8 @@ typedef uint64_t xen_pfn_t;
#define PRI_xen_pfn "llx"
typedef uint64_t xen_ulong_t;
#define PRI_xen_ulong "llx"
+typedef int64_t xen_long_t;
+#define PRI_xen_long "llx"
/* Guest handles for primitive C types. */
__DEFINE_GUEST_HANDLE(uchar, unsigned char);
__DEFINE_GUEST_HANDLE(uint, unsigned int);
diff --git a/arch/arm/include/asm/xen/page.h b/arch/arm/include/asm/xen/page.h
index cf4f3e867395..ded062f9b358 100644
--- a/arch/arm/include/asm/xen/page.h
+++ b/arch/arm/include/asm/xen/page.h
@@ -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))
diff --git a/arch/arm/include/uapi/asm/unistd.h b/arch/arm/include/uapi/asm/unistd.h
index fb5584d0cc05..ba94446c72d9 100644
--- a/arch/arm/include/uapi/asm/unistd.h
+++ b/arch/arm/include/uapi/asm/unistd.h
@@ -408,6 +408,7 @@
#define __NR_finit_module (__NR_SYSCALL_BASE+379)
#define __NR_sched_setattr (__NR_SYSCALL_BASE+380)
#define __NR_sched_getattr (__NR_SYSCALL_BASE+381)
+#define __NR_renameat2 (__NR_SYSCALL_BASE+382)
/*
* This may need to be greater than __NR_last_syscall+1 in order to
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index a766bcbaf8ad..040619c32d68 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -79,6 +79,7 @@ obj-$(CONFIG_CPU_XSCALE) += xscale-cp0.o
obj-$(CONFIG_CPU_XSC3) += xscale-cp0.o
obj-$(CONFIG_CPU_MOHAWK) += xscale-cp0.o
obj-$(CONFIG_CPU_PJ4) += pj4-cp0.o
+obj-$(CONFIG_CPU_PJ4B) += pj4-cp0.o
obj-$(CONFIG_IWMMXT) += iwmmxt.o
obj-$(CONFIG_PERF_EVENTS) += perf_regs.o
obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o perf_event_cpu.o
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index 166e945de832..8f51bdcdacbb 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -391,6 +391,7 @@
CALL(sys_finit_module)
/* 380 */ CALL(sys_sched_setattr)
CALL(sys_sched_getattr)
+ CALL(sys_renameat2)
#ifndef syscalls_counted
.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
#define syscalls_counted
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index 1420725142ca..efb208de75ec 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -132,6 +132,10 @@
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}
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index f8c08839edf3..591d6e4a6492 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -587,7 +587,7 @@ __fixup_pv_table:
add r6, r6, r3 @ adjust __pv_phys_pfn_offset address
add r7, r7, r3 @ adjust __pv_offset address
mov r0, r8, lsr #12 @ convert to PFN
- str r0, [r6, #LOW_OFFSET] @ save computed PHYS_OFFSET to __pv_phys_pfn_offset
+ str r0, [r6] @ save computed PHYS_OFFSET to __pv_phys_pfn_offset
strcc ip, [r7, #HIGH_OFFSET] @ save to __pv_offset high bits
mov r6, r3, lsr #24 @ constant for add/sub instructions
teq r3, r6, lsl #24 @ must be 16MiB aligned
diff --git a/arch/arm/kernel/iwmmxt.S b/arch/arm/kernel/iwmmxt.S
index a08783823b32..2452dd1bef53 100644
--- a/arch/arm/kernel/iwmmxt.S
+++ b/arch/arm/kernel/iwmmxt.S
@@ -19,12 +19,16 @@
#include <asm/thread_info.h>
#include <asm/asm-offsets.h>
-#if defined(CONFIG_CPU_PJ4)
+#if defined(CONFIG_CPU_PJ4) || defined(CONFIG_CPU_PJ4B)
#define PJ4(code...) code
#define XSC(code...)
-#else
+#elif defined(CONFIG_CPU_MOHAWK) || \
+ defined(CONFIG_CPU_XSC3) || \
+ defined(CONFIG_CPU_XSCALE)
#define PJ4(code...)
#define XSC(code...) code
+#else
+#error "Unsupported iWMMXt architecture"
#endif
#define MMX_WR0 (0x00)
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
index f0d180d8b29f..8cf0996aa1a8 100644
--- a/arch/arm/kernel/machine_kexec.c
+++ b/arch/arm/kernel/machine_kexec.c
@@ -184,3 +184,10 @@ void machine_kexec(struct kimage *image)
soft_restart(reboot_entry_phys);
}
+
+void arch_crash_save_vmcoreinfo(void)
+{
+#ifdef CONFIG_ARM_LPAE
+ VMCOREINFO_CONFIG(ARM_LPAE);
+#endif
+}
diff --git a/arch/arm/kernel/pj4-cp0.c b/arch/arm/kernel/pj4-cp0.c
index fc7208636284..8153e36b2491 100644
--- a/arch/arm/kernel/pj4-cp0.c
+++ b/arch/arm/kernel/pj4-cp0.c
@@ -45,7 +45,7 @@ static int iwmmxt_do(struct notifier_block *self, unsigned long cmd, void *t)
return NOTIFY_DONE;
}
-static struct notifier_block iwmmxt_notifier_block = {
+static struct notifier_block __maybe_unused iwmmxt_notifier_block = {
.notifier_call = iwmmxt_do,
};
@@ -72,6 +72,33 @@ static void __init pj4_cp_access_write(u32 value)
: "=r" (temp) : "r" (value));
}
+static int __init pj4_get_iwmmxt_version(void)
+{
+ u32 cp_access, wcid;
+
+ cp_access = pj4_cp_access_read();
+ pj4_cp_access_write(cp_access | 0xf);
+
+ /* check if coprocessor 0 and 1 are available */
+ if ((pj4_cp_access_read() & 0xf) != 0xf) {
+ pj4_cp_access_write(cp_access);
+ return -ENODEV;
+ }
+
+ /* read iWMMXt coprocessor id register p1, c0 */
+ __asm__ __volatile__ ("mrc p1, 0, %0, c0, c0, 0\n" : "=r" (wcid));
+
+ pj4_cp_access_write(cp_access);
+
+ /* iWMMXt v1 */
+ if ((wcid & 0xffffff00) == 0x56051000)
+ return 1;
+ /* iWMMXt v2 */
+ if ((wcid & 0xffffff00) == 0x56052000)
+ return 2;
+
+ return -EINVAL;
+}
/*
* Disable CP0/CP1 on boot, and let call_fpe() and the iWMMXt lazy
@@ -79,17 +106,26 @@ static void __init pj4_cp_access_write(u32 value)
*/
static int __init pj4_cp0_init(void)
{
- u32 cp_access;
+ u32 __maybe_unused cp_access;
+ int vers;
if (!cpu_is_pj4())
return 0;
+ vers = pj4_get_iwmmxt_version();
+ if (vers < 0)
+ return 0;
+
+#ifndef CONFIG_IWMMXT
+ pr_info("PJ4 iWMMXt coprocessor detected, but kernel support is missing.\n");
+#else
cp_access = pj4_cp_access_read() & ~0xf;
pj4_cp_access_write(cp_access);
- printk(KERN_INFO "PJ4 iWMMXt coprocessor enabled.\n");
+ pr_info("PJ4 iWMMXt v%d coprocessor enabled.\n", vers);
elf_hwcap |= HWCAP_IWMMXT;
thread_register_notifier(&iwmmxt_notifier_block);
+#endif
return 0;
}
diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c
index 702bd329d9d0..e90a3148f385 100644
--- a/arch/arm/kernel/sys_oabi-compat.c
+++ b/arch/arm/kernel/sys_oabi-compat.c
@@ -203,9 +203,9 @@ asmlinkage long sys_oabi_fcntl64(unsigned int fd, unsigned int cmd,
int ret;
switch (cmd) {
- case F_GETLKP:
- case F_SETLKP:
- case F_SETLKPW:
+ case F_OFD_GETLK:
+ case F_OFD_SETLK:
+ case F_OFD_SETLKW:
case F_GETLK64:
case F_SETLK64:
case F_SETLKW64:
diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c
index 3c217694ebec..cb791ac6a003 100644
--- a/arch/arm/kernel/unwind.c
+++ b/arch/arm/kernel/unwind.c
@@ -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;
diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig
index 466bd299b1a8..4be5bb150bdd 100644
--- a/arch/arm/kvm/Kconfig
+++ b/arch/arm/kvm/Kconfig
@@ -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.
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index 80bb1e6c2c29..16f804938b8f 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -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;
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index 8b1b0a870025..7cd6f19945ed 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -1296,7 +1296,7 @@ static struct resource adc_resources[] = {
};
static struct platform_device at91_adc_device = {
- .name = "at91_adc",
+ .name = "at91sam9260-adc",
.id = -1,
.dev = {
.platform_data = &adc_data,
@@ -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,
},
};
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 77b04c2edd78..dab362c06487 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -1204,7 +1204,7 @@ static struct resource adc_resources[] = {
};
static struct platform_device at91_adc_device = {
- .name = "at91_adc",
+ .name = "at91sam9g45-adc",
.id = -1,
.dev = {
.platform_data = &adc_data,
diff --git a/arch/arm/mach-exynos/firmware.c b/arch/arm/mach-exynos/firmware.c
index 932129ef26c6..aa01c4222b40 100644
--- a/arch/arm/mach-exynos/firmware.c
+++ b/arch/arm/mach-exynos/firmware.c
@@ -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;
diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
index b0e7f9d2c245..2b4d6acfa34a 100644
--- a/arch/arm/mach-imx/clk-imx6q.c
+++ b/arch/arm/mach-imx/clk-imx6q.c
@@ -208,8 +208,8 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
* the "output_enable" bit as a gate, even though it's really just
* enabling clock output.
*/
- clk[lvds1_gate] = imx_clk_gate("lvds1_gate", "dummy", base + 0x160, 10);
- clk[lvds2_gate] = imx_clk_gate("lvds2_gate", "dummy", base + 0x160, 11);
+ clk[lvds1_gate] = imx_clk_gate("lvds1_gate", "lvds1_sel", base + 0x160, 10);
+ clk[lvds2_gate] = imx_clk_gate("lvds2_gate", "lvds2_sel", base + 0x160, 11);
/* name parent_name reg idx */
clk[pll2_pfd0_352m] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus", base + 0x100, 0);
@@ -258,14 +258,14 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk[ipu2_sel] = imx_clk_mux("ipu2_sel", base + 0x3c, 14, 2, ipu_sels, ARRAY_SIZE(ipu_sels));
clk[ldb_di0_sel] = imx_clk_mux_flags("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT);
clk[ldb_di1_sel] = imx_clk_mux_flags("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT);
- clk[ipu1_di0_pre_sel] = imx_clk_mux("ipu1_di0_pre_sel", base + 0x34, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels));
- clk[ipu1_di1_pre_sel] = imx_clk_mux("ipu1_di1_pre_sel", base + 0x34, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels));
- clk[ipu2_di0_pre_sel] = imx_clk_mux("ipu2_di0_pre_sel", base + 0x38, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels));
- clk[ipu2_di1_pre_sel] = imx_clk_mux("ipu2_di1_pre_sel", base + 0x38, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels));
- clk[ipu1_di0_sel] = imx_clk_mux("ipu1_di0_sel", base + 0x34, 0, 3, ipu1_di0_sels, ARRAY_SIZE(ipu1_di0_sels));
- clk[ipu1_di1_sel] = imx_clk_mux("ipu1_di1_sel", base + 0x34, 9, 3, ipu1_di1_sels, ARRAY_SIZE(ipu1_di1_sels));
- clk[ipu2_di0_sel] = imx_clk_mux("ipu2_di0_sel", base + 0x38, 0, 3, ipu2_di0_sels, ARRAY_SIZE(ipu2_di0_sels));
- clk[ipu2_di1_sel] = imx_clk_mux("ipu2_di1_sel", base + 0x38, 9, 3, ipu2_di1_sels, ARRAY_SIZE(ipu2_di1_sels));
+ clk[ipu1_di0_pre_sel] = imx_clk_mux_flags("ipu1_di0_pre_sel", base + 0x34, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
+ clk[ipu1_di1_pre_sel] = imx_clk_mux_flags("ipu1_di1_pre_sel", base + 0x34, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
+ clk[ipu2_di0_pre_sel] = imx_clk_mux_flags("ipu2_di0_pre_sel", base + 0x38, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
+ clk[ipu2_di1_pre_sel] = imx_clk_mux_flags("ipu2_di1_pre_sel", base + 0x38, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
+ clk[ipu1_di0_sel] = imx_clk_mux_flags("ipu1_di0_sel", base + 0x34, 0, 3, ipu1_di0_sels, ARRAY_SIZE(ipu1_di0_sels), CLK_SET_RATE_PARENT);
+ clk[ipu1_di1_sel] = imx_clk_mux_flags("ipu1_di1_sel", base + 0x34, 9, 3, ipu1_di1_sels, ARRAY_SIZE(ipu1_di1_sels), CLK_SET_RATE_PARENT);
+ clk[ipu2_di0_sel] = imx_clk_mux_flags("ipu2_di0_sel", base + 0x38, 0, 3, ipu2_di0_sels, ARRAY_SIZE(ipu2_di0_sels), CLK_SET_RATE_PARENT);
+ clk[ipu2_di1_sel] = imx_clk_mux_flags("ipu2_di1_sel", base + 0x38, 9, 3, ipu2_di1_sels, ARRAY_SIZE(ipu2_di1_sels), CLK_SET_RATE_PARENT);
clk[hsi_tx_sel] = imx_clk_mux("hsi_tx_sel", base + 0x30, 28, 1, hsi_tx_sels, ARRAY_SIZE(hsi_tx_sels));
clk[pcie_axi_sel] = imx_clk_mux("pcie_axi_sel", base + 0x18, 10, 1, pcie_axi_sels, ARRAY_SIZE(pcie_axi_sels));
clk[ssi1_sel] = imx_clk_fixup_mux("ssi1_sel", base + 0x1c, 10, 2, ssi_sels, ARRAY_SIZE(ssi_sels), imx_cscmr1_fixup);
@@ -445,6 +445,15 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk_set_parent(clk[ldb_di1_sel], clk[pll5_video_div]);
}
+ clk_set_parent(clk[ipu1_di0_pre_sel], clk[pll5_video_div]);
+ clk_set_parent(clk[ipu1_di1_pre_sel], clk[pll5_video_div]);
+ clk_set_parent(clk[ipu2_di0_pre_sel], clk[pll5_video_div]);
+ clk_set_parent(clk[ipu2_di1_pre_sel], clk[pll5_video_div]);
+ clk_set_parent(clk[ipu1_di0_sel], clk[ipu1_di0_pre]);
+ clk_set_parent(clk[ipu1_di1_sel], clk[ipu1_di1_pre]);
+ clk_set_parent(clk[ipu2_di0_sel], clk[ipu2_di0_pre]);
+ clk_set_parent(clk[ipu2_di1_sel], clk[ipu2_di1_pre]);
+
/*
* The gpmi needs 100MHz frequency in the EDO/Sync mode,
* We can not get the 100MHz from the pll2_pfd0_352m.
diff --git a/arch/arm/mach-imx/devices/platform-ipu-core.c b/arch/arm/mach-imx/devices/platform-ipu-core.c
index fc4dd7cedc11..6bd7c3f37ac0 100644
--- a/arch/arm/mach-imx/devices/platform-ipu-core.c
+++ b/arch/arm/mach-imx/devices/platform-ipu-core.c
@@ -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)
diff --git a/arch/arm/mach-lpc32xx/phy3250.c b/arch/arm/mach-lpc32xx/phy3250.c
index 34932e0e31fa..7858d5b6f6ce 100644
--- a/arch/arm/mach-lpc32xx/phy3250.c
+++ b/arch/arm/mach-lpc32xx/phy3250.c
@@ -202,9 +202,6 @@ static struct mmci_platform_data lpc32xx_mmci_data = {
.ocr_mask = MMC_VDD_30_31 | MMC_VDD_31_32 |
MMC_VDD_32_33 | MMC_VDD_33_34,
.ios_handler = mmc_handle_ios,
- .dma_filter = NULL,
- /* No DMA for now since AMBA PL080 dmaengine driver only does scatter
- * gather, and the MMCI driver doesn't do it this way */
};
static struct lpc32xx_slc_platform_data lpc32xx_slc_data = {
diff --git a/arch/arm/mach-mvebu/mvebu-soc-id.c b/arch/arm/mach-mvebu/mvebu-soc-id.c
index f3d4cf53f746..09520e19b78e 100644
--- a/arch/arm/mach-mvebu/mvebu-soc-id.c
+++ b/arch/arm/mach-mvebu/mvebu-soc-id.c
@@ -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);
diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index ac82512b9c8c..b6885e42c0a0 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -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 */
diff --git a/arch/arm/mach-omap2/board-rx51-video.c b/arch/arm/mach-omap2/board-rx51-video.c
index 43a90c8d6837..9cfebc5c7455 100644
--- a/arch/arm/mach-omap2/board-rx51-video.c
+++ b/arch/arm/mach-omap2/board-rx51-video.c
@@ -48,7 +48,7 @@ static struct omap_dss_board_info rx51_dss_board_info = {
static int __init rx51_video_init(void)
{
- if (!machine_is_nokia_rx51() && !of_machine_is_compatible("nokia,omap3-n900"))
+ if (!machine_is_nokia_rx51())
return 0;
if (omap_mux_init_gpio(RX51_LCD_RESET_GPIO, OMAP_PIN_OUTPUT)) {
diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c
index 8f5121b89688..eb8c75ec3b1a 100644
--- a/arch/arm/mach-omap2/cclock3xxx_data.c
+++ b/arch/arm/mach-omap2/cclock3xxx_data.c
@@ -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",
diff --git a/arch/arm/mach-omap2/clkt_dpll.c b/arch/arm/mach-omap2/clkt_dpll.c
index 2649ce445845..332af927f4d3 100644
--- a/arch/arm/mach-omap2/clkt_dpll.c
+++ b/arch/arm/mach-omap2/clkt_dpll.c
@@ -209,7 +209,7 @@ u8 omap2_init_dpll_parent(struct clk_hw *hw)
if (v == OMAP3XXX_EN_DPLL_LPBYPASS ||
v == OMAP3XXX_EN_DPLL_FRBYPASS)
return 1;
- } else if (soc_is_am33xx() || cpu_is_omap44xx()) {
+ } else if (soc_is_am33xx() || cpu_is_omap44xx() || soc_is_am43xx()) {
if (v == OMAP4XXX_EN_DPLL_LPBYPASS ||
v == OMAP4XXX_EN_DPLL_FRBYPASS ||
v == OMAP4XXX_EN_DPLL_MNBYPASS)
@@ -255,7 +255,7 @@ unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk)
if (v == OMAP3XXX_EN_DPLL_LPBYPASS ||
v == OMAP3XXX_EN_DPLL_FRBYPASS)
return __clk_get_rate(dd->clk_bypass);
- } else if (soc_is_am33xx() || cpu_is_omap44xx()) {
+ } else if (soc_is_am33xx() || cpu_is_omap44xx() || soc_is_am43xx()) {
if (v == OMAP4XXX_EN_DPLL_LPBYPASS ||
v == OMAP4XXX_EN_DPLL_FRBYPASS ||
v == OMAP4XXX_EN_DPLL_MNBYPASS)
diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c
index 01fc710c8181..2498ab025fa2 100644
--- a/arch/arm/mach-omap2/cpuidle44xx.c
+++ b/arch/arm/mach-omap2/cpuidle44xx.c
@@ -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);
}
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index ab43755364f5..9fe8c949305c 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -501,7 +501,7 @@ static int gpmc_cs_delete_mem(int cs)
int r;
spin_lock(&gpmc_mem_lock);
- r = release_resource(&gpmc_cs_mem[cs]);
+ r = release_resource(res);
res->start = 0;
res->end = 0;
spin_unlock(&gpmc_mem_lock);
@@ -527,6 +527,14 @@ static int gpmc_cs_remap(int cs, u32 base)
pr_err("%s: requested chip-select is disabled\n", __func__);
return -ENODEV;
}
+
+ /*
+ * Make sure we ignore any device offsets from the GPMC partition
+ * allocated for the chip select and that the new base confirms
+ * to the GPMC 16MB minimum granularity.
+ */
+ base &= ~(SZ_16M - 1);
+
gpmc_cs_get_memconf(cs, &old_base, &size);
if (base == old_base)
return 0;
@@ -586,6 +594,8 @@ EXPORT_SYMBOL(gpmc_cs_request);
void gpmc_cs_free(int cs)
{
+ struct resource *res = &gpmc_cs_mem[cs];
+
spin_lock(&gpmc_mem_lock);
if (cs >= gpmc_cs_num || cs < 0 || !gpmc_cs_reserved(cs)) {
printk(KERN_ERR "Trying to free non-reserved GPMC CS%d\n", cs);
@@ -594,7 +604,8 @@ void gpmc_cs_free(int cs)
return;
}
gpmc_cs_disable_mem(cs);
- release_resource(&gpmc_cs_mem[cs]);
+ if (res->flags)
+ release_resource(res);
gpmc_cs_set_reserved(cs, 0);
spin_unlock(&gpmc_mem_lock);
}
diff --git a/arch/arm/mach-omap2/omap-headsmp.S b/arch/arm/mach-omap2/omap-headsmp.S
index 75e92952c18e..40c5d5f1451c 100644
--- a/arch/arm/mach-omap2/omap-headsmp.S
+++ b/arch/arm/mach-omap2/omap-headsmp.S
@@ -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>
@@ -28,9 +28,13 @@
* 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
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 1f33f5db10d5..66c60fe1104c 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -2546,11 +2546,12 @@ static int __init _init(struct omap_hwmod *oh, void *data)
return -EINVAL;
}
- if (np)
+ if (np) {
if (of_find_property(np, "ti,no-reset-on-init", NULL))
oh->flags |= HWMOD_INIT_NO_RESET;
if (of_find_property(np, "ti,no-idle-on-init", NULL))
oh->flags |= HWMOD_INIT_NO_IDLE;
+ }
oh->_state = _HWMOD_STATE_INITIALIZED;
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index a123ff0070bd..71ac7d5f3385 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -1964,7 +1964,7 @@ static struct omap_hwmod_irq_info omap3xxx_usb_host_hs_irqs[] = {
static struct omap_hwmod omap3xxx_usb_host_hs_hwmod = {
.name = "usb_host_hs",
.class = &omap3xxx_usb_host_hs_hwmod_class,
- .clkdm_name = "l3_init_clkdm",
+ .clkdm_name = "usbhost_clkdm",
.mpu_irqs = omap3xxx_usb_host_hs_irqs,
.main_clk = "usbhost_48m_fck",
.prcm = {
@@ -2047,7 +2047,7 @@ static struct omap_hwmod_irq_info omap3xxx_usb_tll_hs_irqs[] = {
static struct omap_hwmod omap3xxx_usb_tll_hs_hwmod = {
.name = "usb_tll_hs",
.class = &omap3xxx_usb_tll_hs_hwmod_class,
- .clkdm_name = "l3_init_clkdm",
+ .clkdm_name = "core_l4_clkdm",
.mpu_irqs = omap3xxx_usb_tll_hs_irqs,
.main_clk = "usbtll_fck",
.prcm = {
diff --git a/arch/arm/mach-omap2/omap_hwmod_54xx_data.c b/arch/arm/mach-omap2/omap_hwmod_54xx_data.c
index 892317294fdc..e829664e6a6c 100644
--- a/arch/arm/mach-omap2/omap_hwmod_54xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_54xx_data.c
@@ -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 = {
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 1f3770a8a728..87099bb6de69 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -330,10 +330,6 @@ void omap_sram_idle(void)
omap3_sram_restore_context();
omap2_sms_restore_context();
}
- if (core_next_state == PWRDM_POWER_OFF)
- omap2_prm_clear_mod_reg_bits(OMAP3430_AUTO_OFF_MASK,
- OMAP3430_GR_MOD,
- OMAP3_PRM_VOLTCTRL_OFFSET);
}
omap3_intc_resume_idle();
diff --git a/arch/arm/mach-orion5x/common.h b/arch/arm/mach-orion5x/common.h
index f565f9944af2..7548db2bfb8a 100644
--- a/arch/arm/mach-orion5x/common.h
+++ b/arch/arm/mach-orion5x/common.h
@@ -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
/*
diff --git a/arch/arm/mach-pxa/include/mach/hx4700.h b/arch/arm/mach-pxa/include/mach/hx4700.h
index 8bc02913517c..0e1bb46264f9 100644
--- a/arch/arm/mach-pxa/include/mach/hx4700.h
+++ b/arch/arm/mach-pxa/include/mach/hx4700.h
@@ -14,6 +14,7 @@
#include <linux/gpio.h>
#include <linux/mfd/asic3.h>
+#include "irqs.h" /* PXA_NR_BUILTIN_GPIO */
#define HX4700_ASIC3_GPIO_BASE PXA_NR_BUILTIN_GPIO
#define HX4700_EGPIO_BASE (HX4700_ASIC3_GPIO_BASE + ASIC3_NUM_GPIOS)
diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index dbfa5a26cfff..072842f6491b 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -152,7 +152,7 @@ static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)
node = of_find_compatible_node(NULL, NULL, "rockchip,rk3066-pmu");
if (!node) {
- pr_err("%s: could not find sram dt node\n", __func__);
+ pr_err("%s: could not find pmu dt node\n", __func__);
return;
}
diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
index 2858f380beae..486063db2a2f 100644
--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
@@ -992,6 +992,7 @@ static struct asoc_simple_card_info fsi_wm8978_info = {
.platform = "sh_fsi2",
.daifmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM,
.cpu_dai = {
+ .fmt = SND_SOC_DAIFMT_IB_NF,
.name = "fsia-dai",
},
.codec_dai = {
diff --git a/arch/arm/mach-shmobile/board-lager.c b/arch/arm/mach-shmobile/board-lager.c
index f0104bfe544e..18c7e0311aa6 100644
--- a/arch/arm/mach-shmobile/board-lager.c
+++ b/arch/arm/mach-shmobile/board-lager.c
@@ -588,14 +588,12 @@ static struct asoc_simple_card_info rsnd_card_info = {
.card = "SSI01-AK4643",
.codec = "ak4642-codec.2-0012",
.platform = "rcar_sound",
- .daifmt = SND_SOC_DAIFMT_LEFT_J,
+ .daifmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM,
.cpu_dai = {
.name = "rcar_sound",
- .fmt = SND_SOC_DAIFMT_CBS_CFS,
},
.codec_dai = {
.name = "ak4642-hifi",
- .fmt = SND_SOC_DAIFMT_CBM_CFM,
.sysclk = 11289600,
},
};
diff --git a/arch/arm/mach-shmobile/clock-r8a7778.c b/arch/arm/mach-shmobile/clock-r8a7778.c
index 2009a9bc6356..9989b1b06ffd 100644
--- a/arch/arm/mach-shmobile/clock-r8a7778.c
+++ b/arch/arm/mach-shmobile/clock-r8a7778.c
@@ -170,7 +170,7 @@ static struct clk mstp_clks[MSTP_NR] = {
[MSTP010] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 10, 0), /* SSI2 */
[MSTP009] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 9, 0), /* SSI3 */
[MSTP008] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 8, 0), /* SRU */
- [MSTP007] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 7, 0), /* HSPI */
+ [MSTP007] = SH_CLK_MSTP32(&s_clk, MSTPCR0, 7, 0), /* HSPI */
};
static struct clk_lookup lookups[] = {
diff --git a/arch/arm/mach-spear/headsmp.S b/arch/arm/mach-spear/headsmp.S
index ed85473a047f..c52192dc3d9f 100644
--- a/arch/arm/mach-spear/headsmp.S
+++ b/arch/arm/mach-spear/headsmp.S
@@ -3,7 +3,7 @@
*
* Picked from realview
* Copyright (c) 2012 ST Microelectronics Limited
- * Shiraz Hashim <shiraz.hashim@st.com>
+ * Shiraz Hashim <shiraz.linux.kernel@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
diff --git a/arch/arm/mach-spear/platsmp.c b/arch/arm/mach-spear/platsmp.c
index 5c4a19887b2b..c19751fff2c6 100644
--- a/arch/arm/mach-spear/platsmp.c
+++ b/arch/arm/mach-spear/platsmp.c
@@ -4,7 +4,7 @@
* based upon linux/arch/arm/mach-realview/platsmp.c
*
* Copyright (C) 2012 ST Microelectronics Ltd.
- * Shiraz Hashim <shiraz.hashim@st.com>
+ * Shiraz Hashim <shiraz.linux.kernel@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
diff --git a/arch/arm/mach-spear/time.c b/arch/arm/mach-spear/time.c
index 218ba5b67d92..26fda4ed4d51 100644
--- a/arch/arm/mach-spear/time.c
+++ b/arch/arm/mach-spear/time.c
@@ -2,7 +2,7 @@
* arch/arm/plat-spear/time.c
*
* Copyright (C) 2010 ST Microelectronics
- * Shiraz Hashim<shiraz.hashim@st.com>
+ * Shiraz Hashim<shiraz.linux.kernel@gmail.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
@@ -71,7 +71,7 @@ static void clockevent_set_mode(enum clock_event_mode mode,
static int clockevent_next_event(unsigned long evt,
struct clock_event_device *clk_event_dev);
-static void spear_clocksource_init(void)
+static void __init spear_clocksource_init(void)
{
u32 tick_rate;
u16 val;
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index 92d660f9610f..55b305d51669 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -70,7 +70,4 @@ config TEGRA_AHB
which controls AHB bus master arbitration and some
performance parameters(priority, prefech size).
-config TEGRA_EMC_SCALING_ENABLE
- bool "Enable scaling the memory frequency"
-
endmenu
diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile
index de544aabf292..9741de956b3e 100644
--- a/arch/arm/mach-ux500/Makefile
+++ b/arch/arm/mach-ux500/Makefile
@@ -5,8 +5,7 @@
obj-y := cpu.o id.o timer.o pm.o
obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o
obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o
-obj-$(CONFIG_MACH_MOP500) += board-mop500-sdi.o \
- board-mop500-regulators.o \
+obj-$(CONFIG_MACH_MOP500) += board-mop500-regulators.o \
board-mop500-audio.o
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c
deleted file mode 100644
index fcbf3a13a539..000000000000
--- a/arch/arm/mach-ux500/board-mop500-sdi.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * Author: Hanumath Prasad <hanumath.prasad@stericsson.com>
- * License terms: GNU General Public License (GPL) version 2
- */
-
-#include <linux/kernel.h>
-#include <linux/gpio.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/mmci.h>
-#include <linux/mmc/host.h>
-#include <linux/platform_device.h>
-#include <linux/platform_data/dma-ste-dma40.h>
-
-#include <asm/mach-types.h>
-
-#include "db8500-regs.h"
-#include "board-mop500.h"
-#include "ste-dma40-db8500.h"
-
-/*
- * v2 has a new version of this block that need to be forced, the number found
- * in hardware is incorrect
- */
-#define U8500_SDI_V2_PERIPHID 0x10480180
-
-/*
- * SDI 0 (MicroSD slot)
- */
-
-#ifdef CONFIG_STE_DMA40
-struct stedma40_chan_cfg mop500_sdi0_dma_cfg_rx = {
- .mode = STEDMA40_MODE_LOGICAL,
- .dir = DMA_DEV_TO_MEM,
- .dev_type = DB8500_DMA_DEV29_SD_MM0,
-};
-
-static struct stedma40_chan_cfg mop500_sdi0_dma_cfg_tx = {
- .mode = STEDMA40_MODE_LOGICAL,
- .dir = DMA_MEM_TO_DEV,
- .dev_type = DB8500_DMA_DEV29_SD_MM0,
-};
-#endif
-
-struct mmci_platform_data mop500_sdi0_data = {
- .f_max = 100000000,
- .capabilities = MMC_CAP_4_BIT_DATA |
- MMC_CAP_SD_HIGHSPEED |
- MMC_CAP_MMC_HIGHSPEED |
- MMC_CAP_ERASE |
- MMC_CAP_UHS_SDR12 |
- MMC_CAP_UHS_SDR25,
- .gpio_wp = -1,
- .sigdir = MCI_ST_FBCLKEN |
- MCI_ST_CMDDIREN |
- MCI_ST_DATA0DIREN |
- MCI_ST_DATA2DIREN,
-#ifdef CONFIG_STE_DMA40
- .dma_filter = stedma40_filter,
- .dma_rx_param = &mop500_sdi0_dma_cfg_rx,
- .dma_tx_param = &mop500_sdi0_dma_cfg_tx,
-#endif
-};
-
-/*
- * SDI1 (SDIO WLAN)
- */
-#ifdef CONFIG_STE_DMA40
-static struct stedma40_chan_cfg sdi1_dma_cfg_rx = {
- .mode = STEDMA40_MODE_LOGICAL,
- .dir = DMA_DEV_TO_MEM,
- .dev_type = DB8500_DMA_DEV32_SD_MM1,
-};
-
-static struct stedma40_chan_cfg sdi1_dma_cfg_tx = {
- .mode = STEDMA40_MODE_LOGICAL,
- .dir = DMA_MEM_TO_DEV,
- .dev_type = DB8500_DMA_DEV32_SD_MM1,
-};
-#endif
-
-struct mmci_platform_data mop500_sdi1_data = {
- .ocr_mask = MMC_VDD_29_30,
- .f_max = 100000000,
- .capabilities = MMC_CAP_4_BIT_DATA |
- MMC_CAP_NONREMOVABLE,
- .gpio_cd = -1,
- .gpio_wp = -1,
-#ifdef CONFIG_STE_DMA40
- .dma_filter = stedma40_filter,
- .dma_rx_param = &sdi1_dma_cfg_rx,
- .dma_tx_param = &sdi1_dma_cfg_tx,
-#endif
-};
-
-/*
- * SDI 2 (POP eMMC, not on DB8500ed)
- */
-
-#ifdef CONFIG_STE_DMA40
-struct stedma40_chan_cfg mop500_sdi2_dma_cfg_rx = {
- .mode = STEDMA40_MODE_LOGICAL,
- .dir = DMA_DEV_TO_MEM,
- .dev_type = DB8500_DMA_DEV28_SD_MM2,
-};
-
-static struct stedma40_chan_cfg mop500_sdi2_dma_cfg_tx = {
- .mode = STEDMA40_MODE_LOGICAL,
- .dir = DMA_MEM_TO_DEV,
- .dev_type = DB8500_DMA_DEV28_SD_MM2,
-};
-#endif
-
-struct mmci_platform_data mop500_sdi2_data = {
- .ocr_mask = MMC_VDD_165_195,
- .f_max = 100000000,
- .capabilities = MMC_CAP_4_BIT_DATA |
- MMC_CAP_8_BIT_DATA |
- MMC_CAP_NONREMOVABLE |
- MMC_CAP_MMC_HIGHSPEED |
- MMC_CAP_ERASE |
- MMC_CAP_CMD23,
- .gpio_cd = -1,
- .gpio_wp = -1,
-#ifdef CONFIG_STE_DMA40
- .dma_filter = stedma40_filter,
- .dma_rx_param = &mop500_sdi2_dma_cfg_rx,
- .dma_tx_param = &mop500_sdi2_dma_cfg_tx,
-#endif
-};
-
-/*
- * SDI 4 (on-board eMMC)
- */
-
-#ifdef CONFIG_STE_DMA40
-struct stedma40_chan_cfg mop500_sdi4_dma_cfg_rx = {
- .mode = STEDMA40_MODE_LOGICAL,
- .dir = DMA_DEV_TO_MEM,
- .dev_type = DB8500_DMA_DEV42_SD_MM4,
-};
-
-static struct stedma40_chan_cfg mop500_sdi4_dma_cfg_tx = {
- .mode = STEDMA40_MODE_LOGICAL,
- .dir = DMA_MEM_TO_DEV,
- .dev_type = DB8500_DMA_DEV42_SD_MM4,
-};
-#endif
-
-struct mmci_platform_data mop500_sdi4_data = {
- .f_max = 100000000,
- .capabilities = MMC_CAP_4_BIT_DATA |
- MMC_CAP_8_BIT_DATA |
- MMC_CAP_NONREMOVABLE |
- MMC_CAP_MMC_HIGHSPEED |
- MMC_CAP_ERASE |
- MMC_CAP_CMD23,
- .gpio_cd = -1,
- .gpio_wp = -1,
-#ifdef CONFIG_STE_DMA40
- .dma_filter = stedma40_filter,
- .dma_rx_param = &mop500_sdi4_dma_cfg_rx,
- .dma_tx_param = &mop500_sdi4_dma_cfg_tx,
-#endif
-};
diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h
index 32cc0d8d8a0e..7c7b0adca582 100644
--- a/arch/arm/mach-ux500/board-mop500.h
+++ b/arch/arm/mach-ux500/board-mop500.h
@@ -8,12 +8,7 @@
#define __BOARD_MOP500_H
#include <linux/platform_data/asoc-ux500-msp.h>
-#include <linux/amba/mmci.h>
-extern struct mmci_platform_data mop500_sdi0_data;
-extern struct mmci_platform_data mop500_sdi1_data;
-extern struct mmci_platform_data mop500_sdi2_data;
-extern struct mmci_platform_data mop500_sdi4_data;
extern struct msp_i2s_platform_data msp0_platform_data;
extern struct msp_i2s_platform_data msp1_platform_data;
extern struct msp_i2s_platform_data msp2_platform_data;
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index 8820f602fcd2..fa308f07fae5 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -146,10 +146,6 @@ static struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = {
/* Requires call-back bindings. */
OF_DEV_AUXDATA("arm,cortex-a9-pmu", 0, "arm-pmu", &db8500_pmu_platdata),
/* Requires DMA bindings. */
- OF_DEV_AUXDATA("arm,pl18x", 0x80126000, "sdi0", &mop500_sdi0_data),
- OF_DEV_AUXDATA("arm,pl18x", 0x80118000, "sdi1", &mop500_sdi1_data),
- OF_DEV_AUXDATA("arm,pl18x", 0x80005000, "sdi2", &mop500_sdi2_data),
- OF_DEV_AUXDATA("arm,pl18x", 0x80114000, "sdi4", &mop500_sdi4_data),
OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80123000,
"ux500-msp-i2s.0", &msp0_platform_data),
OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80124000,
diff --git a/arch/arm/mach-vexpress/dcscb.c b/arch/arm/mach-vexpress/dcscb.c
index 788495d35cf9..30b993399ed7 100644
--- a/arch/arm/mach-vexpress/dcscb.c
+++ b/arch/arm/mach-vexpress/dcscb.c
@@ -51,12 +51,14 @@ static int dcscb_allcpus_mask[2];
static int dcscb_power_up(unsigned int cpu, unsigned int cluster)
{
unsigned int rst_hold, cpumask = (1 << cpu);
- unsigned int all_mask = dcscb_allcpus_mask[cluster];
+ unsigned int all_mask;
pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
if (cpu >= 4 || cluster >= 2)
return -EINVAL;
+ all_mask = dcscb_allcpus_mask[cluster];
+
/*
* Since this is called with IRQs enabled, and no arch_spin_lock_irq
* variant exists, we need to disable IRQs manually here.
@@ -101,11 +103,12 @@ static void dcscb_power_down(void)
cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
cpumask = (1 << cpu);
- all_mask = dcscb_allcpus_mask[cluster];
pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
BUG_ON(cpu >= 4 || cluster >= 2);
+ all_mask = dcscb_allcpus_mask[cluster];
+
__mcpm_cpu_going_down(cpu, cluster);
arch_spin_lock(&dcscb_lock);
diff --git a/arch/arm/mach-vexpress/spc.c b/arch/arm/mach-vexpress/spc.c
index c26ef5b92ca7..2c2754e79cb3 100644
--- a/arch/arm/mach-vexpress/spc.c
+++ b/arch/arm/mach-vexpress/spc.c
@@ -392,7 +392,7 @@ static irqreturn_t ve_spc_irq_handler(int irq, void *data)
* +--------------------------+
* | 31 20 | 19 0 |
* +--------------------------+
- * | u_volt | freq(kHz) |
+ * | m_volt | freq(kHz) |
* +--------------------------+
*/
#define MULT_FACTOR 20
@@ -414,7 +414,7 @@ static int ve_spc_populate_opps(uint32_t cluster)
ret = ve_spc_read_sys_cfg(SYSCFG_SCC, off, &data);
if (!ret) {
opps->freq = (data & FREQ_MASK) * MULT_FACTOR;
- opps->u_volt = data >> VOLT_SHIFT;
+ opps->u_volt = (data >> VOLT_SHIFT) * 1000;
} else {
break;
}
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index f5ad9ee70426..5bf7c3c3b301 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -420,29 +420,29 @@ config CPU_32v3
bool
select CPU_USE_DOMAINS if MMU
select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
- select TLS_REG_EMUL if SMP || !MMU
select NEED_KUSER_HELPERS
+ select TLS_REG_EMUL if SMP || !MMU
config CPU_32v4
bool
select CPU_USE_DOMAINS if MMU
select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
- select TLS_REG_EMUL if SMP || !MMU
select NEED_KUSER_HELPERS
+ select TLS_REG_EMUL if SMP || !MMU
config CPU_32v4T
bool
select CPU_USE_DOMAINS if MMU
select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
- select TLS_REG_EMUL if SMP || !MMU
select NEED_KUSER_HELPERS
+ select TLS_REG_EMUL if SMP || !MMU
config CPU_32v5
bool
select CPU_USE_DOMAINS if MMU
select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
- select TLS_REG_EMUL if SMP || !MMU
select NEED_KUSER_HELPERS
+ select TLS_REG_EMUL if SMP || !MMU
config CPU_32v6
bool
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index f62aa0677e5c..6b00be1f971e 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -1963,8 +1963,8 @@ arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, size_t size)
mapping->nr_bitmaps = 1;
mapping->extensions = extensions;
mapping->base = base;
- mapping->size = bitmap_size << PAGE_SHIFT;
mapping->bits = BITS_PER_BYTE * bitmap_size;
+ mapping->size = mapping->bits << PAGE_SHIFT;
spin_lock_init(&mapping->lock);
diff --git a/arch/arm/mm/proc-v7m.S b/arch/arm/mm/proc-v7m.S
index 0c93588fcb91..1ca37c72f12f 100644
--- a/arch/arm/mm/proc-v7m.S
+++ b/arch/arm/mm/proc-v7m.S
@@ -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:
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index 5f5b975887fc..b5608b1f9fbd 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -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);
diff --git a/arch/arm/vfp/vfpdouble.c b/arch/arm/vfp/vfpdouble.c
index 6cac43bd1d86..423f56dd4028 100644
--- a/arch/arm/vfp/vfpdouble.c
+++ b/arch/arm/vfp/vfpdouble.c
@@ -866,6 +866,8 @@ vfp_double_multiply_accumulate(int dd, int dn, int dm, u32 fpscr, u32 negate, ch
vdp.sign = vfp_sign_negate(vdp.sign);
vfp_double_unpack(&vdn, vfp_get_double(dd));
+ if (vdn.exponent == 0 && vdn.significand)
+ vfp_double_normalise_denormal(&vdn);
if (negate & NEG_SUBTRACT)
vdn.sign = vfp_sign_negate(vdn.sign);
diff --git a/arch/arm/vfp/vfpsingle.c b/arch/arm/vfp/vfpsingle.c
index b252631b406b..4f96c1617aae 100644
--- a/arch/arm/vfp/vfpsingle.c
+++ b/arch/arm/vfp/vfpsingle.c
@@ -915,6 +915,8 @@ vfp_single_multiply_accumulate(int sd, int sn, s32 m, u32 fpscr, u32 negate, cha
v = vfp_get_float(sd);
pr_debug("VFP: s%u = %08x\n", sd, v);
vfp_single_unpack(&vsn, v);
+ if (vsn.exponent == 0 && vsn.significand)
+ vfp_single_normalise_denormal(&vsn);
if (negate & NEG_SUBTRACT)
vsn.sign = vfp_sign_negate(vsn.sign);
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
index b96723e258a0..1e632430570b 100644
--- a/arch/arm/xen/enlighten.c
+++ b/arch/arm/xen/enlighten.c
@@ -339,6 +339,14 @@ static int __init xen_pm_init(void)
}
late_initcall(xen_pm_init);
+
+/* empty stubs */
+void xen_arch_pre_suspend(void) { }
+void xen_arch_post_suspend(int suspend_cancelled) { }
+void xen_timer_resume(void) { }
+void xen_arch_resume(void) { }
+
+
/* In the hypervisor.S file. */
EXPORT_SYMBOL_GPL(HYPERVISOR_event_channel_op);
EXPORT_SYMBOL_GPL(HYPERVISOR_grant_table_op);
@@ -350,4 +358,5 @@ EXPORT_SYMBOL_GPL(HYPERVISOR_memory_op);
EXPORT_SYMBOL_GPL(HYPERVISOR_physdev_op);
EXPORT_SYMBOL_GPL(HYPERVISOR_vcpu_op);
EXPORT_SYMBOL_GPL(HYPERVISOR_tmem_op);
+EXPORT_SYMBOL_GPL(HYPERVISOR_multicall);
EXPORT_SYMBOL_GPL(privcmd_call);
diff --git a/arch/arm/xen/hypercall.S b/arch/arm/xen/hypercall.S
index d1cf7b7c2200..44e3a5f10c4c 100644
--- a/arch/arm/xen/hypercall.S
+++ b/arch/arm/xen/hypercall.S
@@ -89,6 +89,7 @@ HYPERCALL2(memory_op);
HYPERCALL2(physdev_op);
HYPERCALL3(vcpu_op);
HYPERCALL1(tmem_op);
+HYPERCALL2(multicall);
ENTRY(privcmd_call)
stmdb sp!, {r4}
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index e6e4d3749a6e..e759af5d7098 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -323,8 +323,6 @@ menu "CPU Power Management"
source "drivers/cpuidle/Kconfig"
-source "kernel/power/Kconfig"
-
source "drivers/cpufreq/Kconfig"
endmenu
diff --git a/arch/arm64/boot/dts/apm-storm.dtsi b/arch/arm64/boot/dts/apm-storm.dtsi
index 93f4b2dd9248..f8c40a66e65d 100644
--- a/arch/arm64/boot/dts/apm-storm.dtsi
+++ b/arch/arm64/boot/dts/apm-storm.dtsi
@@ -307,6 +307,7 @@
<0x0 0x1f21e000 0x0 0x1000>,
<0x0 0x1f217000 0x0 0x1000>;
interrupts = <0x0 0x86 0x4>;
+ dma-coherent;
status = "disabled";
clocks = <&sata01clk 0>;
phys = <&phy1 0>;
@@ -321,6 +322,7 @@
<0x0 0x1f22e000 0x0 0x1000>,
<0x0 0x1f227000 0x0 0x1000>;
interrupts = <0x0 0x87 0x4>;
+ dma-coherent;
status = "ok";
clocks = <&sata23clk 0>;
phys = <&phy2 0>;
@@ -334,6 +336,7 @@
<0x0 0x1f23d000 0x0 0x1000>,
<0x0 0x1f23e000 0x0 0x1000>;
interrupts = <0x0 0x88 0x4>;
+ dma-coherent;
status = "ok";
clocks = <&sata45clk 0>;
phys = <&phy3 0>;
diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index e94f9458aa6f..993bce527b85 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -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 *
diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
index f600d400c07d..aff0292c8f4d 100644
--- a/arch/arm64/include/asm/mmu.h
+++ b/arch/arm64/include/asm/mmu.h
@@ -22,6 +22,9 @@ typedef struct {
void *vdso;
} mm_context_t;
+#define INIT_MM_CONTEXT(name) \
+ .context.id_lock = __RAW_SPIN_LOCK_UNLOCKED(name.context.id_lock),
+
#define ASID(mm) ((mm)->context.id & 0xffff)
extern void paging_init(void);
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 90c811f05a2e..7b1c67a0b485 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -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)
{
diff --git a/arch/arm64/include/asm/tlb.h b/arch/arm64/include/asm/tlb.h
index 72cadf52ca80..80e2c08900d6 100644
--- a/arch/arm64/include/asm/tlb.h
+++ b/arch/arm64/include/asm/tlb.h
@@ -19,6 +19,7 @@
#ifndef __ASM_TLB_H
#define __ASM_TLB_H
+#define __tlb_remove_pmd_tlb_entry __tlb_remove_pmd_tlb_entry
#include <asm-generic/tlb.h>
@@ -99,5 +100,10 @@ static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp,
}
#endif
+static inline void __tlb_remove_pmd_tlb_entry(struct mmu_gather *tlb, pmd_t *pmdp,
+ unsigned long address)
+{
+ tlb_add_flush(tlb, address);
+}
#endif
diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h
index bb8eb8a78e67..c8d8fc17bd5a 100644
--- a/arch/arm64/include/asm/unistd32.h
+++ b/arch/arm64/include/asm/unistd32.h
@@ -403,8 +403,9 @@ __SYSCALL(378, sys_kcmp)
__SYSCALL(379, sys_finit_module)
__SYSCALL(380, sys_sched_setattr)
__SYSCALL(381, sys_sched_getattr)
+__SYSCALL(382, sys_renameat2)
-#define __NR_compat_syscalls 379
+#define __NR_compat_syscalls 383
/*
* Compat syscall numbers used by the AArch64 kernel.
diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
index ed3955a95747..a7fb874b595e 100644
--- a/arch/arm64/kernel/debug-monitors.c
+++ b/arch/arm64/kernel/debug-monitors.c
@@ -318,9 +318,6 @@ static int brk_handler(unsigned long addr, unsigned int esr,
if (call_break_hook(regs, esr) == DBG_HOOK_HANDLED)
return 0;
- pr_warn("unexpected brk exception at %lx, esr=0x%x\n",
- (long)instruction_pointer(regs), esr);
-
if (!user_mode(regs))
return -EFAULT;
diff --git a/arch/arm64/kernel/early_printk.c b/arch/arm64/kernel/early_printk.c
index ffbbdde7aba1..2dc36d00addf 100644
--- a/arch/arm64/kernel/early_printk.c
+++ b/arch/arm64/kernel/early_printk.c
@@ -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;
diff --git a/arch/arm64/kernel/irq.c b/arch/arm64/kernel/irq.c
index 473e5dbf8f39..0f08dfd69ebc 100644
--- a/arch/arm64/kernel/irq.c
+++ b/arch/arm64/kernel/irq.c
@@ -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);
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 720853f70b6b..7ec784653b29 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -393,11 +393,10 @@ void __init setup_arch(char **cmdline_p)
static int __init arm64_device_init(void)
{
- of_clk_init(NULL);
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);
diff --git a/arch/arm64/kernel/time.c b/arch/arm64/kernel/time.c
index 29c39d5d77e3..6815987b50f8 100644
--- a/arch/arm64/kernel/time.c
+++ b/arch/arm64/kernel/time.c
@@ -33,6 +33,7 @@
#include <linux/irq.h>
#include <linux/delay.h>
#include <linux/clocksource.h>
+#include <linux/clk-provider.h>
#include <clocksource/arm_arch_timer.h>
@@ -65,6 +66,7 @@ void __init time_init(void)
{
u32 arch_timer_rate;
+ of_clk_init(NULL);
clocksource_of_init();
arch_timer_rate = arch_timer_get_rate();
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index 0ba347e59f06..c851eb44dc50 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -22,8 +22,11 @@
#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
diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c
index 5e9aec358306..31eb959e9aa8 100644
--- a/arch/arm64/mm/hugetlbpage.c
+++ b/arch/arm64/mm/hugetlbpage.c
@@ -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)
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 6b7e89569a3a..0a472c41a67f 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -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/arm64/xen/hypercall.S b/arch/arm64/xen/hypercall.S
index 531342ec4bcf..8bbe9401f4f0 100644
--- a/arch/arm64/xen/hypercall.S
+++ b/arch/arm64/xen/hypercall.S
@@ -80,6 +80,7 @@ HYPERCALL2(memory_op);
HYPERCALL2(physdev_op);
HYPERCALL3(vcpu_op);
HYPERCALL1(tmem_op);
+HYPERCALL2(multicall);
ENTRY(privcmd_call)
mov x16, x0
diff --git a/arch/hexagon/include/asm/barrier.h b/arch/hexagon/include/asm/barrier.h
deleted file mode 100644
index 4e863daea25b..000000000000
--- a/arch/hexagon/include/asm/barrier.h
+++ /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 */
diff --git a/arch/ia64/include/asm/tlb.h b/arch/ia64/include/asm/tlb.h
index bc5efc7c3f3f..39d64e0df1de 100644
--- a/arch/ia64/include/asm/tlb.h
+++ b/arch/ia64/include/asm/tlb.h
@@ -91,18 +91,9 @@ extern struct ia64_tr_entry *ia64_idtrs[NR_CPUS];
#define RR_RID_MASK 0x00000000ffffff00L
#define RR_TO_RID(val) ((val >> 8) & 0xffffff)
-/*
- * Flush the TLB for address range START to END and, if not in fast mode, release the
- * freed pages that where gathered up to this point.
- */
static inline void
-ia64_tlb_flush_mmu (struct mmu_gather *tlb, unsigned long start, unsigned long end)
+ia64_tlb_flush_mmu_tlbonly(struct mmu_gather *tlb, unsigned long start, unsigned long end)
{
- unsigned long i;
- unsigned int nr;
-
- if (!tlb->need_flush)
- return;
tlb->need_flush = 0;
if (tlb->fullmm) {
@@ -135,6 +126,14 @@ ia64_tlb_flush_mmu (struct mmu_gather *tlb, unsigned long start, unsigned long e
flush_tlb_range(&vma, ia64_thash(start), ia64_thash(end));
}
+}
+
+static inline void
+ia64_tlb_flush_mmu_free(struct mmu_gather *tlb)
+{
+ unsigned long i;
+ unsigned int nr;
+
/* lastly, release the freed pages */
nr = tlb->nr;
@@ -144,6 +143,19 @@ ia64_tlb_flush_mmu (struct mmu_gather *tlb, unsigned long start, unsigned long e
free_page_and_swap_cache(tlb->pages[i]);
}
+/*
+ * Flush the TLB for address range START to END and, if not in fast mode, release the
+ * freed pages that where gathered up to this point.
+ */
+static inline void
+ia64_tlb_flush_mmu (struct mmu_gather *tlb, unsigned long start, unsigned long end)
+{
+ if (!tlb->need_flush)
+ return;
+ ia64_tlb_flush_mmu_tlbonly(tlb, start, end);
+ ia64_tlb_flush_mmu_free(tlb);
+}
+
static inline void __tlb_alloc_page(struct mmu_gather *tlb)
{
unsigned long addr = __get_free_pages(GFP_NOWAIT | __GFP_NOWARN, 0);
@@ -206,6 +218,16 @@ static inline int __tlb_remove_page(struct mmu_gather *tlb, struct page *page)
return tlb->max - tlb->nr;
}
+static inline void tlb_flush_mmu_tlbonly(struct mmu_gather *tlb)
+{
+ ia64_tlb_flush_mmu_tlbonly(tlb, tlb->start_addr, tlb->end_addr);
+}
+
+static inline void tlb_flush_mmu_free(struct mmu_gather *tlb)
+{
+ ia64_tlb_flush_mmu_free(tlb);
+}
+
static inline void tlb_flush_mmu(struct mmu_gather *tlb)
{
ia64_tlb_flush_mmu(tlb, tlb->start_addr, tlb->end_addr);
diff --git a/arch/ia64/include/asm/unistd.h b/arch/ia64/include/asm/unistd.h
index ae763d8bf55a..fb13dc5e8f8c 100644
--- a/arch/ia64/include/asm/unistd.h
+++ b/arch/ia64/include/asm/unistd.h
@@ -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
diff --git a/arch/ia64/include/uapi/asm/unistd.h b/arch/ia64/include/uapi/asm/unistd.h
index 715e85f858de..7de0a2d65da4 100644
--- a/arch/ia64/include/uapi/asm/unistd.h
+++ b/arch/ia64/include/uapi/asm/unistd.h
@@ -327,5 +327,6 @@
#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 */
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index fa8d61a312a7..ba3d03503e84 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -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 */
diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S
index e6f80fcf013b..a4acddad0c78 100644
--- a/arch/ia64/kernel/head.S
+++ b/arch/ia64/kernel/head.S
@@ -259,7 +259,7 @@ start_ap:
* Switch into virtual mode:
*/
movl r16=(IA64_PSR_IT|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFH|IA64_PSR_BN \
- |IA64_PSR_DI|IA64_PSR_AC)
+ |IA64_PSR_DI)
;;
mov cr.ipsr=r16
movl r17=1f
diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S
index 689ffcaa284e..18e794a57248 100644
--- a/arch/ia64/kernel/ivt.S
+++ b/arch/ia64/kernel/ivt.S
@@ -58,7 +58,7 @@
#include <asm/unistd.h>
#include <asm/errno.h>
-#if 1
+#if 0
# define PSR_DEFAULT_BITS psr.ac
#else
# define PSR_DEFAULT_BITS 0
diff --git a/arch/ia64/kvm/vmm_ivt.S b/arch/ia64/kvm/vmm_ivt.S
index 24018484c6e9..397e34a63e18 100644
--- a/arch/ia64/kvm/vmm_ivt.S
+++ b/arch/ia64/kvm/vmm_ivt.S
@@ -64,7 +64,7 @@
#include "kvm_minstate.h"
#include "vti.h"
-#if 1
+#if 0
# define PSR_DEFAULT_BITS psr.ac
#else
# define PSR_DEFAULT_BITS 0
diff --git a/arch/m68k/Kconfig.debug b/arch/m68k/Kconfig.debug
index 229682721240..64776d7ac199 100644
--- a/arch/m68k/Kconfig.debug
+++ b/arch/m68k/Kconfig.debug
@@ -12,12 +12,17 @@ config BOOTPARAM_STRING
config EARLY_PRINTK
bool "Early printk"
- depends on MVME16x || MAC
+ depends on !(SUN3 || M68360 || M68000 || COLDFIRE)
help
Write kernel log output directly to a serial port.
+ Where implemented, output goes to the framebuffer as well.
+ PROM console functionality on Sun 3x is not affected by this option.
+
+ Pass "earlyprintk" on the kernel command line to get a
+ boot console.
This is useful for kernel debugging when your machine crashes very
- early before the console code is initialized.
+ early, i.e. before the normal console driver is loaded.
You should normally say N here, unless you want to debug such a crash.
if !MMU
diff --git a/arch/m68k/amiga/amisound.c b/arch/m68k/amiga/amisound.c
index 2559eefc6aff..90a60d758f8b 100644
--- a/arch/m68k/amiga/amisound.c
+++ b/arch/m68k/amiga/amisound.c
@@ -51,7 +51,7 @@ void __init amiga_init_sound(void)
snd_data = amiga_chip_alloc_res(sizeof(sine_data), &beep_res);
if (!snd_data) {
- printk (KERN_CRIT "amiga init_sound: failed to allocate chipmem\n");
+ pr_crit("amiga init_sound: failed to allocate chipmem\n");
return;
}
memcpy (snd_data, sine_data, sizeof(sine_data));
diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index 9625b7132227..01693df7f2f6 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -183,7 +183,7 @@ int __init amiga_parse_bootinfo(const struct bi_record *record)
dev->boardaddr = be32_to_cpu(cd->cd_BoardAddr);
dev->boardsize = be32_to_cpu(cd->cd_BoardSize);
} else
- printk("amiga_parse_bootinfo: too many AutoConfig devices\n");
+ pr_warn("amiga_parse_bootinfo: too many AutoConfig devices\n");
#endif /* CONFIG_ZORRO */
break;
@@ -209,9 +209,9 @@ static void __init amiga_identify(void)
memset(&amiga_hw_present, 0, sizeof(amiga_hw_present));
- printk("Amiga hardware found: ");
+ pr_info("Amiga hardware found: ");
if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO) {
- printk("[%s] ", amiga_models[amiga_model-AMI_500]);
+ pr_cont("[%s] ", amiga_models[amiga_model-AMI_500]);
strcat(amiga_model_name, amiga_models[amiga_model-AMI_500]);
}
@@ -322,7 +322,7 @@ static void __init amiga_identify(void)
#define AMIGAHW_ANNOUNCE(name, str) \
if (AMIGAHW_PRESENT(name)) \
- printk(str)
+ pr_cont(str)
AMIGAHW_ANNOUNCE(AMI_VIDEO, "VIDEO ");
AMIGAHW_ANNOUNCE(AMI_BLITTER, "BLITTER ");
@@ -354,8 +354,8 @@ static void __init amiga_identify(void)
AMIGAHW_ANNOUNCE(MAGIC_REKICK, "MAGIC_REKICK ");
AMIGAHW_ANNOUNCE(PCMCIA, "PCMCIA ");
if (AMIGAHW_PRESENT(ZORRO))
- printk("ZORRO%s ", AMIGAHW_PRESENT(ZORRO3) ? "3" : "");
- printk("\n");
+ pr_cont("ZORRO%s ", AMIGAHW_PRESENT(ZORRO3) ? "3" : "");
+ pr_cont("\n");
#undef AMIGAHW_ANNOUNCE
}
@@ -424,7 +424,7 @@ void __init config_amiga(void)
if (m68k_memory[i].addr < 16*1024*1024) {
if (i == 0) {
/* don't cut off the branch we're sitting on */
- printk("Warning: kernel runs in Zorro II memory\n");
+ pr_warn("Warning: kernel runs in Zorro II memory\n");
continue;
}
disabled_z2mem += m68k_memory[i].size;
@@ -435,8 +435,8 @@ void __init config_amiga(void)
}
}
if (disabled_z2mem)
- printk("%dK of Zorro II memory will not be used as system memory\n",
- disabled_z2mem>>10);
+ pr_info("%dK of Zorro II memory will not be used as system memory\n",
+ disabled_z2mem>>10);
}
/* request all RAM */
@@ -475,7 +475,7 @@ static void __init amiga_sched_init(irq_handler_t timer_routine)
jiffy_ticks = DIV_ROUND_CLOSEST(amiga_eclock, HZ);
if (request_resource(&mb_resources._ciab, &sched_res))
- printk("Cannot allocate ciab.ta{lo,hi}\n");
+ pr_warn("Cannot allocate ciab.ta{lo,hi}\n");
ciab.cra &= 0xC0; /* turn off timer A, continuous mode, from Eclk */
ciab.talo = jiffy_ticks % 256;
ciab.tahi = jiffy_ticks / 256;
diff --git a/arch/m68k/apollo/config.c b/arch/m68k/apollo/config.c
index 9268c0f96376..6e62d66c396e 100644
--- a/arch/m68k/apollo/config.c
+++ b/arch/m68k/apollo/config.c
@@ -65,8 +65,8 @@ int __init apollo_parse_bootinfo(const struct bi_record *record)
static void __init dn_setup_model(void)
{
- printk("Apollo hardware found: ");
- printk("[%s]\n", apollo_models[apollo_model - APOLLO_DN3000]);
+ pr_info("Apollo hardware found: [%s]\n",
+ apollo_models[apollo_model - APOLLO_DN3000]);
switch(apollo_model) {
case APOLLO_UNKNOWN:
@@ -197,8 +197,10 @@ void dn_sched_init(irq_handler_t timer_routine)
*(volatile unsigned char *)(pica+1)&=(~8);
#if 0
- printk("*(0x10803) %02x\n",*(volatile unsigned char *)(apollo_timer + 0x3));
- printk("*(0x10803) %02x\n",*(volatile unsigned char *)(apollo_timer + 0x3));
+ pr_info("*(0x10803) %02x\n",
+ *(volatile unsigned char *)(apollo_timer + 0x3));
+ pr_info("*(0x10803) %02x\n",
+ *(volatile unsigned char *)(apollo_timer + 0x3));
#endif
if (request_irq(IRQ_APOLLO, dn_timer_int, 0, "time", timer_routine))
@@ -236,12 +238,10 @@ int dn_dummy_hwclk(int op, struct rtc_time *t) {
}
-int dn_dummy_set_clock_mmss(unsigned long nowtime) {
-
- printk("set_clock_mmss\n");
-
- return 0;
-
+int dn_dummy_set_clock_mmss(unsigned long nowtime)
+{
+ pr_info("set_clock_mmss\n");
+ return 0;
}
void dn_dummy_reset(void) {
diff --git a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c
index 0810c8d56e59..5f8cb5a234d9 100644
--- a/arch/m68k/atari/stram.c
+++ b/arch/m68k/atari/stram.c
@@ -47,6 +47,7 @@ static struct resource stram_pool = {
static unsigned long pool_size = 1024*1024;
+static unsigned long stram_virt_offset;
static int __init atari_stram_setup(char *arg)
{
@@ -67,14 +68,12 @@ early_param("stram_pool", atari_stram_setup);
void __init atari_stram_init(void)
{
int i;
- void *stram_start;
/*
* determine whether kernel code resides in ST-RAM
* (then ST-RAM is the first memory block at virtual 0x0)
*/
- stram_start = phys_to_virt(0);
- kernel_in_stram = (stram_start == 0);
+ kernel_in_stram = (m68k_memory[0].addr == 0);
for (i = 0; i < m68k_num_memory; ++i) {
if (m68k_memory[i].addr == 0) {
@@ -89,24 +88,62 @@ void __init atari_stram_init(void)
/*
* This function is called from setup_arch() to reserve the pages needed for
- * ST-RAM management.
+ * ST-RAM management, if the kernel resides in ST-RAM.
*/
void __init atari_stram_reserve_pages(void *start_mem)
{
- /*
- * always reserve first page of ST-RAM, the first 2 KiB are
- * supervisor-only!
- */
- if (!kernel_in_stram)
- reserve_bootmem(0, PAGE_SIZE, BOOTMEM_DEFAULT);
+ if (kernel_in_stram) {
+ pr_debug("atari_stram pool: kernel in ST-RAM, using alloc_bootmem!\n");
+ stram_pool.start = (resource_size_t)alloc_bootmem_low_pages(pool_size);
+ stram_pool.end = stram_pool.start + pool_size - 1;
+ request_resource(&iomem_resource, &stram_pool);
+ stram_virt_offset = 0;
+ pr_debug("atari_stram pool: size = %lu bytes, resource = %pR\n",
+ pool_size, &stram_pool);
+ pr_debug("atari_stram pool: stram_virt_offset = %lx\n",
+ stram_virt_offset);
+ }
+}
- stram_pool.start = (resource_size_t)alloc_bootmem_low_pages(pool_size);
- stram_pool.end = stram_pool.start + pool_size - 1;
- request_resource(&iomem_resource, &stram_pool);
- pr_debug("atari_stram pool: size = %lu bytes, resource = %pR\n",
- pool_size, &stram_pool);
+/*
+ * This function is called as arch initcall to reserve the pages needed for
+ * ST-RAM management, if the kernel does not reside in ST-RAM.
+ */
+int __init atari_stram_map_pages(void)
+{
+ if (!kernel_in_stram) {
+ /*
+ * Skip page 0, as the fhe first 2 KiB are supervisor-only!
+ */
+ pr_debug("atari_stram pool: kernel not in ST-RAM, using ioremap!\n");
+ stram_pool.start = PAGE_SIZE;
+ stram_pool.end = stram_pool.start + pool_size - 1;
+ request_resource(&iomem_resource, &stram_pool);
+ stram_virt_offset = (unsigned long) ioremap(stram_pool.start,
+ resource_size(&stram_pool)) - stram_pool.start;
+ pr_debug("atari_stram pool: size = %lu bytes, resource = %pR\n",
+ pool_size, &stram_pool);
+ pr_debug("atari_stram pool: stram_virt_offset = %lx\n",
+ stram_virt_offset);
+ }
+ return 0;
+}
+arch_initcall(atari_stram_map_pages);
+
+
+void *atari_stram_to_virt(unsigned long phys)
+{
+ return (void *)(phys + stram_virt_offset);
+}
+EXPORT_SYMBOL(atari_stram_to_virt);
+
+
+unsigned long atari_stram_to_phys(void *virt)
+{
+ return (unsigned long)(virt - stram_virt_offset);
}
+EXPORT_SYMBOL(atari_stram_to_phys);
void *atari_stram_alloc(unsigned long size, const char *owner)
@@ -134,14 +171,14 @@ void *atari_stram_alloc(unsigned long size, const char *owner)
}
pr_debug("atari_stram_alloc: returning %pR\n", res);
- return (void *)res->start;
+ return atari_stram_to_virt(res->start);
}
EXPORT_SYMBOL(atari_stram_alloc);
void atari_stram_free(void *addr)
{
- unsigned long start = (unsigned long)addr;
+ unsigned long start = atari_stram_to_phys(addr);
struct resource *res;
unsigned long size;
diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig
index 96da4963d14b..d7eac833a94f 100644
--- a/arch/m68k/configs/amiga_defconfig
+++ b/arch/m68k/configs/amiga_defconfig
@@ -159,6 +159,7 @@ CONFIG_IP_SET_BITMAP_IP=m
CONFIG_IP_SET_BITMAP_IPMAC=m
CONFIG_IP_SET_BITMAP_PORT=m
CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPMARK=m
CONFIG_IP_SET_HASH_IPPORT=m
CONFIG_IP_SET_HASH_IPPORTIP=m
CONFIG_IP_SET_HASH_IPPORTNET=m
@@ -227,6 +228,7 @@ CONFIG_DNS_RESOLVER=y
CONFIG_BATMAN_ADV=m
CONFIG_BATMAN_ADV_DAT=y
CONFIG_BATMAN_ADV_NC=y
+CONFIG_BATMAN_ADV_MCAST=y
CONFIG_NETLINK_DIAG=m
CONFIG_NET_MPLS_GSO=m
# CONFIG_WIRELESS is not set
@@ -279,6 +281,7 @@ CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
CONFIG_DM_CACHE=m
+CONFIG_DM_ERA=m
CONFIG_DM_MIRROR=m
CONFIG_DM_RAID=m
CONFIG_DM_ZERO=m
@@ -305,7 +308,6 @@ CONFIG_VETH=m
CONFIG_A2065=y
CONFIG_ARIADNE=y
# CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_NET_VENDOR_CIRRUS is not set
# CONFIG_NET_VENDOR_HP is not set
@@ -315,6 +317,7 @@ CONFIG_ARIADNE=y
CONFIG_HYDRA=y
CONFIG_APNE=y
CONFIG_ZORRO8390=y
+# CONFIG_NET_VENDOR_SAMSUNG is not set
# CONFIG_NET_VENDOR_SEEQ is not set
# CONFIG_NET_VENDOR_SMSC is not set
# CONFIG_NET_VENDOR_STMICRO is not set
diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig
index 1b8739f50cbf..650ee75de6cd 100644
--- a/arch/m68k/configs/apollo_defconfig
+++ b/arch/m68k/configs/apollo_defconfig
@@ -157,6 +157,7 @@ CONFIG_IP_SET_BITMAP_IP=m
CONFIG_IP_SET_BITMAP_IPMAC=m
CONFIG_IP_SET_BITMAP_PORT=m
CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPMARK=m
CONFIG_IP_SET_HASH_IPPORT=m
CONFIG_IP_SET_HASH_IPPORTIP=m
CONFIG_IP_SET_HASH_IPPORTNET=m
@@ -225,6 +226,7 @@ CONFIG_DNS_RESOLVER=y
CONFIG_BATMAN_ADV=m
CONFIG_BATMAN_ADV_DAT=y
CONFIG_BATMAN_ADV_NC=y
+CONFIG_BATMAN_ADV_MCAST=y
CONFIG_NETLINK_DIAG=m
CONFIG_NET_MPLS_GSO=m
# CONFIG_WIRELESS is not set
@@ -261,6 +263,7 @@ CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
CONFIG_DM_CACHE=m
+CONFIG_DM_ERA=m
CONFIG_DM_MIRROR=m
CONFIG_DM_RAID=m
CONFIG_DM_ZERO=m
@@ -284,12 +287,12 @@ CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
CONFIG_VETH=m
# CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_NET_VENDOR_INTEL is not set
# CONFIG_NET_VENDOR_MARVELL is not set
# CONFIG_NET_VENDOR_MICREL is not set
# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
# CONFIG_NET_VENDOR_SEEQ is not set
# CONFIG_NET_VENDOR_STMICRO is not set
# CONFIG_NET_VENDOR_VIA is not set
diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig
index 6ea4e91f0caa..3142e69342fa 100644
--- a/arch/m68k/configs/atari_defconfig
+++ b/arch/m68k/configs/atari_defconfig
@@ -156,6 +156,7 @@ CONFIG_IP_SET_BITMAP_IP=m
CONFIG_IP_SET_BITMAP_IPMAC=m
CONFIG_IP_SET_BITMAP_PORT=m
CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPMARK=m
CONFIG_IP_SET_HASH_IPPORT=m
CONFIG_IP_SET_HASH_IPPORTIP=m
CONFIG_IP_SET_HASH_IPPORTNET=m
@@ -224,6 +225,7 @@ CONFIG_DNS_RESOLVER=y
CONFIG_BATMAN_ADV=m
CONFIG_BATMAN_ADV_DAT=y
CONFIG_BATMAN_ADV_NC=y
+CONFIG_BATMAN_ADV_MCAST=y
CONFIG_NETLINK_DIAG=m
CONFIG_NET_MPLS_GSO=m
# CONFIG_WIRELESS is not set
@@ -269,6 +271,7 @@ CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
CONFIG_DM_CACHE=m
+CONFIG_DM_ERA=m
CONFIG_DM_MIRROR=m
CONFIG_DM_RAID=m
CONFIG_DM_ZERO=m
@@ -293,11 +296,11 @@ CONFIG_NETCONSOLE_DYNAMIC=y
CONFIG_VETH=m
CONFIG_ATARILANCE=y
# CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_NET_VENDOR_INTEL is not set
# CONFIG_NET_VENDOR_MARVELL is not set
# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
# CONFIG_NET_VENDOR_SEEQ is not set
# CONFIG_NET_VENDOR_STMICRO is not set
# CONFIG_NET_VENDOR_VIA is not set
diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig
index e5a12739ff2d..0daa8a172f30 100644
--- a/arch/m68k/configs/bvme6000_defconfig
+++ b/arch/m68k/configs/bvme6000_defconfig
@@ -155,6 +155,7 @@ CONFIG_IP_SET_BITMAP_IP=m
CONFIG_IP_SET_BITMAP_IPMAC=m
CONFIG_IP_SET_BITMAP_PORT=m
CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPMARK=m
CONFIG_IP_SET_HASH_IPPORT=m
CONFIG_IP_SET_HASH_IPPORTIP=m
CONFIG_IP_SET_HASH_IPPORTNET=m
@@ -223,6 +224,7 @@ CONFIG_DNS_RESOLVER=y
CONFIG_BATMAN_ADV=m
CONFIG_BATMAN_ADV_DAT=y
CONFIG_BATMAN_ADV_NC=y
+CONFIG_BATMAN_ADV_MCAST=y
CONFIG_NETLINK_DIAG=m
CONFIG_NET_MPLS_GSO=m
# CONFIG_WIRELESS is not set
@@ -260,6 +262,7 @@ CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
CONFIG_DM_CACHE=m
+CONFIG_DM_ERA=m
CONFIG_DM_MIRROR=m
CONFIG_DM_RAID=m
CONFIG_DM_ZERO=m
@@ -283,12 +286,12 @@ CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
CONFIG_VETH=m
# CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
CONFIG_BVME6000_NET=y
# CONFIG_NET_VENDOR_MARVELL is not set
# CONFIG_NET_VENDOR_MICREL is not set
# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
# CONFIG_NET_VENDOR_SEEQ is not set
# CONFIG_NET_VENDOR_STMICRO is not set
# CONFIG_NET_VENDOR_VIA is not set
diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig
index 8936d7fb0f0f..88af78f7bad9 100644
--- a/arch/m68k/configs/hp300_defconfig
+++ b/arch/m68k/configs/hp300_defconfig
@@ -157,6 +157,7 @@ CONFIG_IP_SET_BITMAP_IP=m
CONFIG_IP_SET_BITMAP_IPMAC=m
CONFIG_IP_SET_BITMAP_PORT=m
CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPMARK=m
CONFIG_IP_SET_HASH_IPPORT=m
CONFIG_IP_SET_HASH_IPPORTIP=m
CONFIG_IP_SET_HASH_IPPORTNET=m
@@ -225,6 +226,7 @@ CONFIG_DNS_RESOLVER=y
CONFIG_BATMAN_ADV=m
CONFIG_BATMAN_ADV_DAT=y
CONFIG_BATMAN_ADV_NC=y
+CONFIG_BATMAN_ADV_MCAST=y
CONFIG_NETLINK_DIAG=m
CONFIG_NET_MPLS_GSO=m
# CONFIG_WIRELESS is not set
@@ -261,6 +263,7 @@ CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
CONFIG_DM_CACHE=m
+CONFIG_DM_ERA=m
CONFIG_DM_MIRROR=m
CONFIG_DM_RAID=m
CONFIG_DM_ZERO=m
@@ -285,12 +288,12 @@ CONFIG_NETCONSOLE_DYNAMIC=y
CONFIG_VETH=m
CONFIG_HPLANCE=y
# CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_NET_VENDOR_INTEL is not set
# CONFIG_NET_VENDOR_MARVELL is not set
# CONFIG_NET_VENDOR_MICREL is not set
# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
# CONFIG_NET_VENDOR_SEEQ is not set
# CONFIG_NET_VENDOR_STMICRO is not set
# CONFIG_NET_VENDOR_VIA is not set
diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig
index be5342cca25b..66f915574a85 100644
--- a/arch/m68k/configs/mac_defconfig
+++ b/arch/m68k/configs/mac_defconfig
@@ -156,6 +156,7 @@ CONFIG_IP_SET_BITMAP_IP=m
CONFIG_IP_SET_BITMAP_IPMAC=m
CONFIG_IP_SET_BITMAP_PORT=m
CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPMARK=m
CONFIG_IP_SET_HASH_IPPORT=m
CONFIG_IP_SET_HASH_IPPORTIP=m
CONFIG_IP_SET_HASH_IPPORTNET=m
@@ -227,6 +228,7 @@ CONFIG_DNS_RESOLVER=y
CONFIG_BATMAN_ADV=m
CONFIG_BATMAN_ADV_DAT=y
CONFIG_BATMAN_ADV_NC=y
+CONFIG_BATMAN_ADV_MCAST=y
CONFIG_NETLINK_DIAG=m
CONFIG_NET_MPLS_GSO=m
# CONFIG_WIRELESS is not set
@@ -270,6 +272,7 @@ CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
CONFIG_DM_CACHE=m
+CONFIG_DM_ERA=m
CONFIG_DM_MIRROR=m
CONFIG_DM_RAID=m
CONFIG_DM_ZERO=m
@@ -301,7 +304,6 @@ CONFIG_NETCONSOLE_DYNAMIC=y
CONFIG_VETH=m
CONFIG_MACMACE=y
# CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
CONFIG_MAC89x0=y
# CONFIG_NET_VENDOR_INTEL is not set
@@ -309,6 +311,7 @@ CONFIG_MAC89x0=y
# CONFIG_NET_VENDOR_MICREL is not set
CONFIG_MACSONIC=y
CONFIG_MAC8390=y
+# CONFIG_NET_VENDOR_SAMSUNG is not set
# CONFIG_NET_VENDOR_SEEQ is not set
# CONFIG_NET_VENDOR_SMSC is not set
# CONFIG_NET_VENDOR_STMICRO is not set
diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig
index f27194ade167..5eaa49924fa6 100644
--- a/arch/m68k/configs/multi_defconfig
+++ b/arch/m68k/configs/multi_defconfig
@@ -165,6 +165,7 @@ CONFIG_IP_SET_BITMAP_IP=m
CONFIG_IP_SET_BITMAP_IPMAC=m
CONFIG_IP_SET_BITMAP_PORT=m
CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPMARK=m
CONFIG_IP_SET_HASH_IPPORT=m
CONFIG_IP_SET_HASH_IPPORTIP=m
CONFIG_IP_SET_HASH_IPPORTNET=m
@@ -236,6 +237,7 @@ CONFIG_DNS_RESOLVER=y
CONFIG_BATMAN_ADV=m
CONFIG_BATMAN_ADV_DAT=y
CONFIG_BATMAN_ADV_NC=y
+CONFIG_BATMAN_ADV_MCAST=y
CONFIG_NETLINK_DIAG=m
CONFIG_NET_MPLS_GSO=m
# CONFIG_WIRELESS is not set
@@ -302,6 +304,7 @@ CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
CONFIG_DM_CACHE=m
+CONFIG_DM_ERA=m
CONFIG_DM_MIRROR=m
CONFIG_DM_RAID=m
CONFIG_DM_ZERO=m
@@ -340,7 +343,6 @@ CONFIG_MVME147_NET=y
CONFIG_SUN3LANCE=y
CONFIG_MACMACE=y
# CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
CONFIG_MAC89x0=y
# CONFIG_NET_VENDOR_HP is not set
@@ -354,6 +356,7 @@ CONFIG_MAC8390=y
CONFIG_NE2000=m
CONFIG_APNE=y
CONFIG_ZORRO8390=y
+# CONFIG_NET_VENDOR_SAMSUNG is not set
# CONFIG_NET_VENDOR_SEEQ is not set
# CONFIG_NET_VENDOR_STMICRO is not set
# CONFIG_NET_VENDOR_VIA is not set
diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig
index c3887603c1db..324d0b4d8351 100644
--- a/arch/m68k/configs/mvme147_defconfig
+++ b/arch/m68k/configs/mvme147_defconfig
@@ -154,6 +154,7 @@ CONFIG_IP_SET_BITMAP_IP=m
CONFIG_IP_SET_BITMAP_IPMAC=m
CONFIG_IP_SET_BITMAP_PORT=m
CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPMARK=m
CONFIG_IP_SET_HASH_IPPORT=m
CONFIG_IP_SET_HASH_IPPORTIP=m
CONFIG_IP_SET_HASH_IPPORTNET=m
@@ -222,6 +223,7 @@ CONFIG_DNS_RESOLVER=y
CONFIG_BATMAN_ADV=m
CONFIG_BATMAN_ADV_DAT=y
CONFIG_BATMAN_ADV_NC=y
+CONFIG_BATMAN_ADV_MCAST=y
CONFIG_NETLINK_DIAG=m
CONFIG_NET_MPLS_GSO=m
# CONFIG_WIRELESS is not set
@@ -259,6 +261,7 @@ CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
CONFIG_DM_CACHE=m
+CONFIG_DM_ERA=m
CONFIG_DM_MIRROR=m
CONFIG_DM_RAID=m
CONFIG_DM_ZERO=m
@@ -283,12 +286,12 @@ CONFIG_NETCONSOLE_DYNAMIC=y
CONFIG_VETH=m
CONFIG_MVME147_NET=y
# CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_NET_VENDOR_INTEL is not set
# CONFIG_NET_VENDOR_MARVELL is not set
# CONFIG_NET_VENDOR_MICREL is not set
# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
# CONFIG_NET_VENDOR_SEEQ is not set
# CONFIG_NET_VENDOR_STMICRO is not set
# CONFIG_NET_VENDOR_VIA is not set
diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig
index f7ff784d05ac..f0cb4338952e 100644
--- a/arch/m68k/configs/mvme16x_defconfig
+++ b/arch/m68k/configs/mvme16x_defconfig
@@ -155,6 +155,7 @@ CONFIG_IP_SET_BITMAP_IP=m
CONFIG_IP_SET_BITMAP_IPMAC=m
CONFIG_IP_SET_BITMAP_PORT=m
CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPMARK=m
CONFIG_IP_SET_HASH_IPPORT=m
CONFIG_IP_SET_HASH_IPPORTIP=m
CONFIG_IP_SET_HASH_IPPORTNET=m
@@ -223,6 +224,7 @@ CONFIG_DNS_RESOLVER=y
CONFIG_BATMAN_ADV=m
CONFIG_BATMAN_ADV_DAT=y
CONFIG_BATMAN_ADV_NC=y
+CONFIG_BATMAN_ADV_MCAST=y
CONFIG_NETLINK_DIAG=m
CONFIG_NET_MPLS_GSO=m
# CONFIG_WIRELESS is not set
@@ -260,6 +262,7 @@ CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
CONFIG_DM_CACHE=m
+CONFIG_DM_ERA=m
CONFIG_DM_MIRROR=m
CONFIG_DM_RAID=m
CONFIG_DM_ZERO=m
@@ -283,12 +286,12 @@ CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
CONFIG_VETH=m
# CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
CONFIG_MVME16x_NET=y
# CONFIG_NET_VENDOR_MARVELL is not set
# CONFIG_NET_VENDOR_MICREL is not set
# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
# CONFIG_NET_VENDOR_SEEQ is not set
# CONFIG_NET_VENDOR_STMICRO is not set
# CONFIG_NET_VENDOR_VIA is not set
diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig
index f0c72ab037be..d6cf0880c463 100644
--- a/arch/m68k/configs/q40_defconfig
+++ b/arch/m68k/configs/q40_defconfig
@@ -155,6 +155,7 @@ CONFIG_IP_SET_BITMAP_IP=m
CONFIG_IP_SET_BITMAP_IPMAC=m
CONFIG_IP_SET_BITMAP_PORT=m
CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPMARK=m
CONFIG_IP_SET_HASH_IPPORT=m
CONFIG_IP_SET_HASH_IPPORTIP=m
CONFIG_IP_SET_HASH_IPPORTNET=m
@@ -223,6 +224,7 @@ CONFIG_DNS_RESOLVER=y
CONFIG_BATMAN_ADV=m
CONFIG_BATMAN_ADV_DAT=y
CONFIG_BATMAN_ADV_NC=y
+CONFIG_BATMAN_ADV_MCAST=y
CONFIG_NETLINK_DIAG=m
CONFIG_NET_MPLS_GSO=m
# CONFIG_WIRELESS is not set
@@ -266,6 +268,7 @@ CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
CONFIG_DM_CACHE=m
+CONFIG_DM_ERA=m
CONFIG_DM_MIRROR=m
CONFIG_DM_RAID=m
CONFIG_DM_ZERO=m
@@ -291,7 +294,6 @@ CONFIG_VETH=m
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_NET_VENDOR_AMD is not set
# CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_NET_VENDOR_CIRRUS is not set
# CONFIG_NET_VENDOR_HP is not set
@@ -299,6 +301,7 @@ CONFIG_VETH=m
# CONFIG_NET_VENDOR_MARVELL is not set
# CONFIG_NET_VENDOR_MICREL is not set
CONFIG_NE2000=m
+# CONFIG_NET_VENDOR_SAMSUNG is not set
# CONFIG_NET_VENDOR_SEEQ is not set
# CONFIG_NET_VENDOR_SMSC is not set
# CONFIG_NET_VENDOR_STMICRO is not set
diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig
index 7bca0f464521..f4e88d1c7472 100644
--- a/arch/m68k/configs/sun3_defconfig
+++ b/arch/m68k/configs/sun3_defconfig
@@ -152,6 +152,7 @@ CONFIG_IP_SET_BITMAP_IP=m
CONFIG_IP_SET_BITMAP_IPMAC=m
CONFIG_IP_SET_BITMAP_PORT=m
CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPMARK=m
CONFIG_IP_SET_HASH_IPPORT=m
CONFIG_IP_SET_HASH_IPPORTIP=m
CONFIG_IP_SET_HASH_IPPORTNET=m
@@ -220,6 +221,7 @@ CONFIG_DNS_RESOLVER=y
CONFIG_BATMAN_ADV=m
CONFIG_BATMAN_ADV_DAT=y
CONFIG_BATMAN_ADV_NC=y
+CONFIG_BATMAN_ADV_MCAST=y
CONFIG_NETLINK_DIAG=m
CONFIG_NET_MPLS_GSO=m
# CONFIG_WIRELESS is not set
@@ -257,6 +259,7 @@ CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
CONFIG_DM_CACHE=m
+CONFIG_DM_ERA=m
CONFIG_DM_MIRROR=m
CONFIG_DM_RAID=m
CONFIG_DM_ZERO=m
@@ -281,11 +284,11 @@ CONFIG_NETCONSOLE_DYNAMIC=y
CONFIG_VETH=m
CONFIG_SUN3LANCE=y
# CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
CONFIG_SUN3_82586=y
# CONFIG_NET_VENDOR_MARVELL is not set
# CONFIG_NET_VENDOR_MICREL is not set
# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
# CONFIG_NET_VENDOR_SEEQ is not set
# CONFIG_NET_VENDOR_STMICRO is not set
# CONFIG_NET_VENDOR_SUN is not set
diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig
index 317f3e1fec95..49f4032c1ad6 100644
--- a/arch/m68k/configs/sun3x_defconfig
+++ b/arch/m68k/configs/sun3x_defconfig
@@ -152,6 +152,7 @@ CONFIG_IP_SET_BITMAP_IP=m
CONFIG_IP_SET_BITMAP_IPMAC=m
CONFIG_IP_SET_BITMAP_PORT=m
CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPMARK=m
CONFIG_IP_SET_HASH_IPPORT=m
CONFIG_IP_SET_HASH_IPPORTIP=m
CONFIG_IP_SET_HASH_IPPORTNET=m
@@ -220,6 +221,7 @@ CONFIG_DNS_RESOLVER=y
CONFIG_BATMAN_ADV=m
CONFIG_BATMAN_ADV_DAT=y
CONFIG_BATMAN_ADV_NC=y
+CONFIG_BATMAN_ADV_MCAST=y
CONFIG_NETLINK_DIAG=m
CONFIG_NET_MPLS_GSO=m
# CONFIG_WIRELESS is not set
@@ -257,6 +259,7 @@ CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
CONFIG_DM_CACHE=m
+CONFIG_DM_ERA=m
CONFIG_DM_MIRROR=m
CONFIG_DM_RAID=m
CONFIG_DM_ZERO=m
@@ -281,12 +284,12 @@ CONFIG_NETCONSOLE_DYNAMIC=y
CONFIG_VETH=m
CONFIG_SUN3LANCE=y
# CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_NET_VENDOR_INTEL is not set
# CONFIG_NET_VENDOR_MARVELL is not set
# CONFIG_NET_VENDOR_MICREL is not set
# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
# CONFIG_NET_VENDOR_SEEQ is not set
# CONFIG_NET_VENDOR_STMICRO is not set
# CONFIG_NET_VENDOR_VIA is not set
diff --git a/arch/m68k/hp300/config.c b/arch/m68k/hp300/config.c
index 2e5a787ea11b..a9befe65adc4 100644
--- a/arch/m68k/hp300/config.c
+++ b/arch/m68k/hp300/config.c
@@ -87,7 +87,7 @@ int __init hp300_parse_bootinfo(const struct bi_record *record)
/* serial port address: ignored here */
break;
- default:
+ default:
unknown = 1;
}
@@ -262,11 +262,12 @@ void __init config_hp300(void)
#endif
mach_max_dma_address = 0xffffffff;
- if (hp300_model >= HP_330 && hp300_model <= HP_433S && hp300_model != HP_350) {
- printk(KERN_INFO "Detected HP9000 model %s\n", hp300_models[hp300_model-HP_320]);
+ if (hp300_model >= HP_330 && hp300_model <= HP_433S &&
+ hp300_model != HP_350) {
+ pr_info("Detected HP9000 model %s\n",
+ hp300_models[hp300_model-HP_320]);
strcat(hp300_model_name, hp300_models[hp300_model-HP_320]);
- }
- else {
+ } else {
panic("Unknown HP9000 Model");
}
#ifdef CONFIG_SERIAL_8250_CONSOLE
diff --git a/arch/m68k/include/asm/atari_stram.h b/arch/m68k/include/asm/atari_stram.h
index 62e27598af91..4e771c22d6a9 100644
--- a/arch/m68k/include/asm/atari_stram.h
+++ b/arch/m68k/include/asm/atari_stram.h
@@ -8,6 +8,8 @@
/* public interface */
void *atari_stram_alloc(unsigned long size, const char *owner);
void atari_stram_free(void *);
+void *atari_stram_to_virt(unsigned long phys);
+unsigned long atari_stram_to_phys(void *);
/* functions called internally by other parts of the kernel */
void atari_stram_init(void);
diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h
index 9d38b73989eb..33afa56ad47a 100644
--- a/arch/m68k/include/asm/unistd.h
+++ b/arch/m68k/include/asm/unistd.h
@@ -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
diff --git a/arch/m68k/include/uapi/asm/unistd.h b/arch/m68k/include/uapi/asm/unistd.h
index b932dd470041..9cd82fbc7817 100644
--- a/arch/m68k/include/uapi/asm/unistd.h
+++ b/arch/m68k/include/uapi/asm/unistd.h
@@ -356,5 +356,6 @@
#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_ */
diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile
index 2d5d9be16273..e47778f8588d 100644
--- a/arch/m68k/kernel/Makefile
+++ b/arch/m68k/kernel/Makefile
@@ -25,3 +25,5 @@ obj-$(CONFIG_HAS_DMA) += dma.o
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
obj-$(CONFIG_BOOTINFO_PROC) += bootinfo_proc.o
+obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+
diff --git a/arch/m68k/kernel/early_printk.c b/arch/m68k/kernel/early_printk.c
new file mode 100644
index 000000000000..ff9708d71921
--- /dev/null
+++ b/arch/m68k/kernel/early_printk.c
@@ -0,0 +1,67 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2014 Finn Thain
+ */
+
+#include <linux/kernel.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <asm/setup.h>
+
+extern void mvme16x_cons_write(struct console *co,
+ const char *str, unsigned count);
+
+asmlinkage void __init debug_cons_nputs(const char *s, unsigned n);
+
+static void __ref debug_cons_write(struct console *c,
+ const char *s, unsigned n)
+{
+#if !(defined(CONFIG_SUN3) || defined(CONFIG_M68360) || \
+ defined(CONFIG_M68000) || defined(CONFIG_COLDFIRE))
+ if (MACH_IS_MVME16x)
+ mvme16x_cons_write(c, s, n);
+ else
+ debug_cons_nputs(s, n);
+#endif
+}
+
+static struct console early_console_instance = {
+ .name = "debug",
+ .write = debug_cons_write,
+ .flags = CON_PRINTBUFFER | CON_BOOT,
+ .index = -1
+};
+
+static int __init setup_early_printk(char *buf)
+{
+ if (early_console || buf)
+ return 0;
+
+ early_console = &early_console_instance;
+ register_console(early_console);
+
+ return 0;
+}
+early_param("earlyprintk", setup_early_printk);
+
+/*
+ * debug_cons_nputs() defined in arch/m68k/kernel/head.S cannot be called
+ * after init sections are discarded (for platforms that use it).
+ */
+#if !(defined(CONFIG_SUN3) || defined(CONFIG_M68360) || \
+ defined(CONFIG_M68000) || defined(CONFIG_COLDFIRE))
+
+static int __init unregister_early_console(void)
+{
+ if (!early_console || MACH_IS_MVME16x)
+ return 0;
+
+ return unregister_console(early_console);
+}
+late_initcall(unregister_early_console);
+
+#endif
diff --git a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S
index 3ab329b88521..dbb118e1a4e0 100644
--- a/arch/m68k/kernel/head.S
+++ b/arch/m68k/kernel/head.S
@@ -153,7 +153,7 @@
* ------------
* The console is also able to be turned off. The console in head.S
* is specifically for debugging and can be very useful. It is surrounded by
- * #ifdef CONSOLE/#endif clauses so it doesn't have to ship in known-good
+ * #ifdef / #endif clauses so it doesn't have to ship in known-good
* kernels. It's basic algorithm is to determine the size of the screen
* (in height/width and bit depth) and then use that information for
* displaying an 8x8 font or an 8x16 (widthxheight). I prefer the 8x8 for
@@ -198,9 +198,8 @@
* CONFIG_xxx: These are the obvious machine configuration defines created
* during configuration. These are defined in autoconf.h.
*
- * CONSOLE: There is support for head.S console in this file. This
- * console can talk to a Mac frame buffer, but could easily be extrapolated
- * to extend it to support other platforms.
+ * CONSOLE_DEBUG: Only supports a Mac frame buffer but could easily be
+ * extended to support other platforms.
*
* TEST_MMU: This is a test harness for running on any given machine but
* getting an MMU dump for another class of machine. The classes of machines
@@ -222,7 +221,7 @@
* MMU_PRINT: There is a routine built into head.S that can display the
* MMU data structures. It outputs its result through the serial_putc
* interface. So where ever that winds up driving data, that's where the
- * mmu struct will appear. On the Macintosh that's typically the console.
+ * mmu struct will appear.
*
* SERIAL_DEBUG: There are a series of putc() macro statements
* scattered through out the code to give progress of status to the
@@ -250,8 +249,8 @@
* USE_MFP: Use the ST-MFP port (Modem1) for serial debug.
*
* Macintosh constants:
- * MAC_USE_SCC_A: Use SCC port A (modem) for serial debug and early console.
- * MAC_USE_SCC_B: Use SCC port B (printer) for serial debug and early console.
+ * MAC_USE_SCC_A: Use SCC port A (modem) for serial debug.
+ * MAC_USE_SCC_B: Use SCC port B (printer) for serial debug.
*/
#include <linux/linkage.h>
@@ -268,27 +267,17 @@
#include <asm/pgtable.h>
#include <asm/page.h>
#include <asm/asm-offsets.h>
-
#ifdef CONFIG_MAC
-
-#include <asm/machw.h>
-
-#ifdef CONFIG_FRAMEBUFFER_CONSOLE
-#define CONSOLE
+# include <asm/machw.h>
#endif
#ifdef CONFIG_EARLY_PRINTK
-#define SERIAL_DEBUG
-#else
-#undef SERIAL_DEBUG
+# define SERIAL_DEBUG
+# if defined(CONFIG_MAC) && defined(CONFIG_FONT_SUPPORT)
+# define CONSOLE_DEBUG
+# endif
#endif
-#else /* !CONFIG_MAC */
-
-#define SERIAL_DEBUG
-
-#endif /* !CONFIG_MAC */
-
#undef MMU_PRINT
#undef MMU_NOCACHE_KERNEL
#undef DEBUG
@@ -303,6 +292,7 @@
.globl kernel_pg_dir
.globl availmem
+.globl m68k_init_mapped_size
.globl m68k_pgtable_cachemode
.globl m68k_supervisor_cachemode
#ifdef CONFIG_MVME16x
@@ -480,22 +470,21 @@ func_define serial_putc,1
func_define console_putc,1
func_define console_init
-func_define console_put_stats
func_define console_put_penguin
func_define console_plot_pixel,3
func_define console_scroll
.macro putc ch
-#if defined(CONSOLE) || defined(SERIAL_DEBUG)
+#if defined(CONSOLE_DEBUG) || defined(SERIAL_DEBUG)
pea \ch
#endif
-#ifdef CONSOLE
+#ifdef CONSOLE_DEBUG
func_call console_putc
#endif
#ifdef SERIAL_DEBUG
func_call serial_putc
#endif
-#if defined(CONSOLE) || defined(SERIAL_DEBUG)
+#if defined(CONSOLE_DEBUG) || defined(SERIAL_DEBUG)
addql #4,%sp
#endif
.endm
@@ -515,7 +504,7 @@ func_define putn,1
.endm
.macro puts string
-#if defined(CONSOLE) || defined(SERIAL_DEBUG)
+#if defined(CONSOLE_DEBUG) || defined(SERIAL_DEBUG)
__INITDATA
.Lstr\@:
.string "\string"
@@ -651,11 +640,9 @@ ENTRY(__start)
lea %pc@(L(mac_rowbytes)),%a1
movel %a0@,%a1@
-#ifdef SERIAL_DEBUG
get_bi_record BI_MAC_SCCBASE
lea %pc@(L(mac_sccbase)),%a1
movel %a0@,%a1@
-#endif
L(test_notmac):
#endif /* CONFIG_MAC */
@@ -885,13 +872,12 @@ L(nothp):
*/
#ifdef CONFIG_MAC
is_not_mac(L(nocon))
-# ifdef CONSOLE
+# ifdef CONSOLE_DEBUG
console_init
# ifdef CONFIG_LOGO
console_put_penguin
# endif /* CONFIG_LOGO */
- console_put_stats
-# endif /* CONSOLE */
+# endif /* CONSOLE_DEBUG */
L(nocon):
#endif /* CONFIG_MAC */
@@ -922,10 +908,21 @@ L(nocon):
*
* This block of code does what's necessary to map in the various kinds
* of machines for execution of Linux.
- * First map the first 4 MB of kernel code & data
+ * First map the first 4, 8, or 16 MB of kernel code & data
*/
- mmu_map #PAGE_OFFSET,%pc@(L(phys_kernel_start)),#4*1024*1024,\
+ get_bi_record BI_MEMCHUNK
+ movel %a0@(4),%d0
+ movel #16*1024*1024,%d1
+ cmpl %d0,%d1
+ jls 1f
+ lsrl #1,%d1
+ cmpl %d0,%d1
+ jls 1f
+ lsrl #1,%d1
+1:
+ movel %d1,m68k_init_mapped_size
+ mmu_map #PAGE_OFFSET,%pc@(L(phys_kernel_start)),%d1,\
%pc@(m68k_supervisor_cachemode)
putc 'C'
@@ -1396,15 +1393,13 @@ L(mmu_fixup_done):
andl L(mac_videobase),%d0
addl #VIDEOMEMBASE,%d0
movel %d0,L(mac_videobase)
-#if defined(CONSOLE)
+#ifdef CONSOLE_DEBUG
movel %pc@(L(phys_kernel_start)),%d0
subl #PAGE_OFFSET,%d0
subl %d0,L(console_font)
subl %d0,L(console_font_data)
#endif
-#ifdef SERIAL_DEBUG
orl #0x50000000,L(mac_sccbase)
-#endif
1:
#endif
@@ -2734,7 +2729,12 @@ func_return get_new_page
*/
#ifdef CONFIG_MAC
+/* You may define either or both of these. */
+#define MAC_USE_SCC_A /* Modem port */
+#define MAC_USE_SCC_B /* Printer port */
+#if defined(MAC_USE_SCC_A) || defined(MAC_USE_SCC_B)
+/* Initialisation table for SCC with 3.6864 MHz PCLK */
L(scc_initable_mac):
.byte 4,0x44 /* x16, 1 stopbit, no parity */
.byte 3,0xc0 /* receiver: 8 bpc */
@@ -2748,6 +2748,7 @@ L(scc_initable_mac):
.byte -1
.even
#endif
+#endif /* CONFIG_MAC */
#ifdef CONFIG_ATARI
/* #define USE_PRINTER */
@@ -2756,14 +2757,12 @@ L(scc_initable_mac):
#define USE_MFP
#if defined(USE_SCC_A) || defined(USE_SCC_B)
-#define USE_SCC
-/* Initialisation table for SCC */
-L(scc_initable):
- .byte 9,12 /* Reset */
+/* Initialisation table for SCC with 7.9872 MHz PCLK */
+/* PCLK == 8.0539 gives baud == 9680.1 */
+L(scc_initable_atari):
.byte 4,0x44 /* x16, 1 stopbit, no parity */
.byte 3,0xc0 /* receiver: 8 bpc */
.byte 5,0xe2 /* transmitter: 8 bpc, assert dtr/rts */
- .byte 9,0 /* no interrupts */
.byte 10,0 /* NRZ */
.byte 11,0x50 /* use baud rate generator */
.byte 12,24,13,0 /* 9600 baud */
@@ -2812,7 +2811,7 @@ LMFP_UDR = 0xfffa2f
*/
/*
- * Initialize serial port hardware for 9600/8/1
+ * Initialize serial port hardware
*/
func_start serial_init,%d0/%d1/%a0/%a1
/*
@@ -2822,7 +2821,7 @@ func_start serial_init,%d0/%d1/%a0/%a1
* d0 = boot info offset
* CONFIG_ATARI
* a0 = address of SCC
- * a1 = Liobase address/address of scc_initable
+ * a1 = Liobase address/address of scc_initable_atari
* d0 = init data for serial port
* CONFIG_MAC
* a0 = address of SCC
@@ -2843,6 +2842,7 @@ func_start serial_init,%d0/%d1/%a0/%a1
| movew #61,CUSTOMBASE+C_SERPER-ZTWOBASE
1:
#endif
+
#ifdef CONFIG_ATARI
is_not_atari(4f)
movel %pc@(L(iobase)),%a1
@@ -2857,9 +2857,21 @@ func_start serial_init,%d0/%d1/%a0/%a1
moveb %a1@(LPSG_READ),%d0
bset #5,%d0
moveb %d0,%a1@(LPSG_WRITE)
-#elif defined(USE_SCC)
+#elif defined(USE_SCC_A) || defined(USE_SCC_B)
lea %a1@(LSCC_CTRL),%a0
- lea %pc@(L(scc_initable)),%a1
+ /* Reset SCC register pointer */
+ moveb %a0@,%d0
+ /* Reset SCC device: write register pointer then register value */
+ moveb #9,%a0@
+ moveb #0xc0,%a0@
+ /* Wait for 5 PCLK cycles, which is about 63 CPU cycles */
+ /* 5 / 7.9872 MHz = approx. 0.63 us = 63 / 100 MHz */
+ movel #32,%d0
+2:
+ subq #1,%d0
+ jne 2b
+ /* Initialize channel */
+ lea %pc@(L(scc_initable_atari)),%a1
2: moveb %a1@+,%d0
jmi 3f
moveb %d0,%a0@
@@ -2877,21 +2889,14 @@ func_start serial_init,%d0/%d1/%a0/%a1
jra L(serial_init_done)
4:
#endif
+
#ifdef CONFIG_MAC
is_not_mac(L(serial_init_not_mac))
-
-#ifdef SERIAL_DEBUG
-
-/* You may define either or both of these. */
-#define MAC_USE_SCC_A /* Modem port */
-#define MAC_USE_SCC_B /* Printer port */
-
+#if defined(MAC_USE_SCC_A) || defined(MAC_USE_SCC_B)
#define mac_scc_cha_b_ctrl_offset 0x0
#define mac_scc_cha_a_ctrl_offset 0x2
#define mac_scc_cha_b_data_offset 0x4
#define mac_scc_cha_a_data_offset 0x6
-
-#if defined(MAC_USE_SCC_A) || defined(MAC_USE_SCC_B)
movel %pc@(L(mac_sccbase)),%a0
/* Reset SCC register pointer */
moveb %a0@(mac_scc_cha_a_ctrl_offset),%d0
@@ -2905,7 +2910,6 @@ func_start serial_init,%d0/%d1/%a0/%a1
subq #1,%d0
jne 5b
#endif
-
#ifdef MAC_USE_SCC_A
/* Initialize channel A */
lea %pc@(L(scc_initable_mac)),%a1
@@ -2916,7 +2920,6 @@ func_start serial_init,%d0/%d1/%a0/%a1
jra 5b
6:
#endif /* MAC_USE_SCC_A */
-
#ifdef MAC_USE_SCC_B
/* Initialize channel B */
lea %pc@(L(scc_initable_mac)),%a1
@@ -2927,9 +2930,6 @@ func_start serial_init,%d0/%d1/%a0/%a1
jra 7b
8:
#endif /* MAC_USE_SCC_B */
-
-#endif /* SERIAL_DEBUG */
-
jra L(serial_init_done)
L(serial_init_not_mac):
#endif /* CONFIG_MAC */
@@ -2959,6 +2959,15 @@ L(serial_init_not_mac):
2:
#endif
+#ifdef CONFIG_MVME16x
+ is_not_mvme16x(L(serial_init_not_mvme16x))
+ moveb #0x10,M167_PCSCCMICR
+ moveb #0x10,M167_PCSCCTICR
+ moveb #0x10,M167_PCSCCRICR
+ jra L(serial_init_done)
+L(serial_init_not_mvme16x):
+#endif
+
#ifdef CONFIG_APOLLO
/* We count on the PROM initializing SIO1 */
#endif
@@ -2998,27 +3007,19 @@ func_start serial_putc,%d0/%d1/%a0/%a1
#ifdef CONFIG_MAC
is_not_mac(5f)
-
-#ifdef SERIAL_DEBUG
-
#if defined(MAC_USE_SCC_A) || defined(MAC_USE_SCC_B)
movel %pc@(L(mac_sccbase)),%a1
#endif
-
#ifdef MAC_USE_SCC_A
3: btst #2,%a1@(mac_scc_cha_a_ctrl_offset)
jeq 3b
moveb %d0,%a1@(mac_scc_cha_a_data_offset)
#endif /* MAC_USE_SCC_A */
-
#ifdef MAC_USE_SCC_B
4: btst #2,%a1@(mac_scc_cha_b_ctrl_offset)
jeq 4b
moveb %d0,%a1@(mac_scc_cha_b_data_offset)
#endif /* MAC_USE_SCC_B */
-
-#endif /* SERIAL_DEBUG */
-
jra L(serial_putc_done)
5:
#endif /* CONFIG_MAC */
@@ -3039,7 +3040,7 @@ func_start serial_putc,%d0/%d1/%a0/%a1
nop
bset #5,%d0
moveb %d0,%a1@(LPSG_WRITE)
-#elif defined(USE_SCC)
+#elif defined(USE_SCC_A) || defined(USE_SCC_B)
3: btst #2,%a1@(LSCC_CTRL)
jeq 3b
moveb %d0,%a1@(LSCC_DATA)
@@ -3195,7 +3196,7 @@ func_start puts,%d0/%a0
movel ARG1,%a0
jra 2f
1:
-#ifdef CONSOLE
+#ifdef CONSOLE_DEBUG
console_putc %d0
#endif
#ifdef SERIAL_DEBUG
@@ -3224,7 +3225,7 @@ func_start putn,%d0-%d2
jls 2f
addb #'A'-('9'+1),%d2
2:
-#ifdef CONSOLE
+#ifdef CONSOLE_DEBUG
console_putc %d2
#endif
#ifdef SERIAL_DEBUG
@@ -3234,21 +3235,19 @@ func_start putn,%d0-%d2
func_return putn
-#ifdef CONFIG_MAC
+#ifdef CONFIG_EARLY_PRINTK
/*
- * mac_early_print
- *
* This routine takes its parameters on the stack. It then
* turns around and calls the internal routines. This routine
* is used by the boot console.
*
* The calling parameters are:
- * void mac_early_print(const char *str, unsigned length);
+ * void debug_cons_nputs(const char *str, unsigned length)
*
* This routine does NOT understand variable arguments only
* simple strings!
*/
-ENTRY(mac_early_print)
+ENTRY(debug_cons_nputs)
moveml %d0/%d1/%a0,%sp@-
movew %sr,%sp@-
ori #0x0700,%sr
@@ -3256,7 +3255,7 @@ ENTRY(mac_early_print)
movel %sp@(22),%d1 /* fetch parameter */
jra 2f
1:
-#ifdef CONSOLE
+#ifdef CONSOLE_DEBUG
console_putc %d0
#endif
#ifdef SERIAL_DEBUG
@@ -3270,7 +3269,7 @@ ENTRY(mac_early_print)
movew %sp@+,%sr
moveml %sp@+,%d0/%d1/%a0
rts
-#endif /* CONFIG_MAC */
+#endif /* CONFIG_EARLY_PRINTK */
#if defined(CONFIG_HP300) || defined(CONFIG_APOLLO)
func_start set_leds,%d0/%a0
@@ -3292,7 +3291,7 @@ func_start set_leds,%d0/%a0
func_return set_leds
#endif
-#ifdef CONSOLE
+#ifdef CONSOLE_DEBUG
/*
* For continuity, see the data alignment
* to which this structure is tied.
@@ -3396,43 +3395,6 @@ L(console_clear_loop):
1:
func_return console_init
-func_start console_put_stats,%a0/%d7
- /*
- * Some of the register usage that follows
- * a0 = pointer to boot_info
- * d7 = value of boot_info fields
- */
- puts "\nMacLinux\n"
-
-#ifdef SERIAL_DEBUG
- puts "\n vidaddr:"
- putn %pc@(L(mac_videobase)) /* video addr. */
-
- puts "\n _stext:"
- lea %pc@(_stext),%a0
- putn %a0
-
- puts "\nbootinfo:"
- lea %pc@(_end),%a0
- putn %a0
-
- puts "\n cpuid:"
- putn %pc@(L(cputype))
-
-# ifdef CONFIG_MAC
- puts "\n sccbase:"
- putn %pc@(L(mac_sccbase))
-# endif
-# ifdef MMU_PRINT
- putc '\n'
- jbsr mmu_print_machine_cpu_types
-# endif
-#endif /* SERIAL_DEBUG */
-
- putc '\n'
-
-func_return console_put_stats
-
#ifdef CONFIG_LOGO
func_start console_put_penguin,%a0-%a1/%d0-%d7
/*
@@ -3774,12 +3736,15 @@ L(white_16):
L(console_plot_pixel_exit):
func_return console_plot_pixel
-#endif /* CONSOLE */
+#endif /* CONSOLE_DEBUG */
__INITDATA
.align 4
+m68k_init_mapped_size:
+ .long 0
+
#if defined(CONFIG_ATARI) || defined(CONFIG_AMIGA) || \
defined(CONFIG_HP300) || defined(CONFIG_APOLLO)
L(custom):
@@ -3787,7 +3752,7 @@ L(iobase):
.long 0
#endif
-#if defined(CONSOLE)
+#ifdef CONSOLE_DEBUG
L(console_globals):
.long 0 /* cursor column */
.long 0 /* cursor row */
@@ -3798,7 +3763,7 @@ L(console_font):
.long 0 /* pointer to console font (struct font_desc) */
L(console_font_data):
.long 0 /* pointer to console font data */
-#endif /* CONSOLE */
+#endif /* CONSOLE_DEBUG */
#if defined(MMU_PRINT)
L(mmu_print_data):
@@ -3838,7 +3803,9 @@ M167_CYIER = 0xfff45011
M167_CYLICR = 0xfff45026
M167_CYTEOIR = 0xfff45085
M167_CYTDR = 0xfff450f8
+M167_PCSCCMICR = 0xfff4201d
M167_PCSCCTICR = 0xfff4201e
+M167_PCSCCRICR = 0xfff4201f
M167_PCTPIACKR = 0xfff42025
#endif
@@ -3856,10 +3823,8 @@ L(mac_dimensions):
.long 0
L(mac_rowbytes):
.long 0
-#ifdef SERIAL_DEBUG
L(mac_sccbase):
.long 0
-#endif
#endif /* CONFIG_MAC */
#if defined (CONFIG_APOLLO)
diff --git a/arch/m68k/kernel/syscalltable.S b/arch/m68k/kernel/syscalltable.S
index b6223dc41d82..501e10212789 100644
--- a/arch/m68k/kernel/syscalltable.S
+++ b/arch/m68k/kernel/syscalltable.S
@@ -371,4 +371,5 @@ ENTRY(sys_call_table)
.long sys_finit_module
.long sys_sched_setattr
.long sys_sched_getattr /* 350 */
+ .long sys_renameat2
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index 982c3fe73c4a..a471eab1a4dd 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -71,31 +71,6 @@ static void mac_get_model(char *str);
static void mac_identify(void);
static void mac_report_hardware(void);
-#ifdef CONFIG_EARLY_PRINTK
-asmlinkage void __init mac_early_print(const char *s, unsigned n);
-
-static void __init mac_early_cons_write(struct console *con,
- const char *s, unsigned n)
-{
- mac_early_print(s, n);
-}
-
-static struct console __initdata mac_early_cons = {
- .name = "early",
- .write = mac_early_cons_write,
- .flags = CON_PRINTBUFFER | CON_BOOT,
- .index = -1
-};
-
-int __init mac_unregister_early_cons(void)
-{
- /* mac_early_print can't be used after init sections are discarded */
- return unregister_console(&mac_early_cons);
-}
-
-late_initcall(mac_unregister_early_cons);
-#endif
-
static void __init mac_sched_init(irq_handler_t vector)
{
via_init_clock(vector);
@@ -190,10 +165,6 @@ void __init config_mac(void)
mach_beep = mac_mksound;
#endif
-#ifdef CONFIG_EARLY_PRINTK
- register_console(&mac_early_cons);
-#endif
-
/*
* Determine hardware present
*/
diff --git a/arch/m68k/mm/motorola.c b/arch/m68k/mm/motorola.c
index 7d4024432163..b958916e5eac 100644
--- a/arch/m68k/mm/motorola.c
+++ b/arch/m68k/mm/motorola.c
@@ -45,7 +45,7 @@ EXPORT_SYMBOL(mm_cachebits);
#endif
/* size of memory already mapped in head.S */
-#define INIT_MAPPED_SIZE (4UL<<20)
+extern __initdata unsigned long m68k_init_mapped_size;
extern unsigned long availmem;
@@ -271,10 +271,12 @@ void __init paging_init(void)
*/
addr = m68k_memory[0].addr;
size = m68k_memory[0].size;
- free_bootmem_node(NODE_DATA(0), availmem, min(INIT_MAPPED_SIZE, size) - (availmem - addr));
+ free_bootmem_node(NODE_DATA(0), availmem,
+ min(m68k_init_mapped_size, size) - (availmem - addr));
map_node(0);
- if (size > INIT_MAPPED_SIZE)
- free_bootmem_node(NODE_DATA(0), addr + INIT_MAPPED_SIZE, size - INIT_MAPPED_SIZE);
+ if (size > m68k_init_mapped_size)
+ free_bootmem_node(NODE_DATA(0), addr + m68k_init_mapped_size,
+ size - m68k_init_mapped_size);
for (i = 1; i < m68k_num_memory; i++)
map_node(i);
diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c
index eab7d342757e..a53803cc66cd 100644
--- a/arch/m68k/mvme16x/config.c
+++ b/arch/m68k/mvme16x/config.c
@@ -213,7 +213,7 @@ static void __init mvme16x_init_IRQ (void)
#define CySCRH (0x22)
#define CyTFTC (0x80)
-static void cons_write(struct console *co, const char *str, unsigned count)
+void mvme16x_cons_write(struct console *co, const char *str, unsigned count)
{
volatile unsigned char *base_addr = (u_char *)CD2401_ADDR;
volatile u_char sink;
@@ -268,20 +268,6 @@ static void cons_write(struct console *co, const char *str, unsigned count)
base_addr[CyIER] = ier;
}
-static struct console cons_info =
-{
- .name = "sercon",
- .write = cons_write,
- .flags = CON_PRINTBUFFER | CON_BOOT,
- .index = -1,
-};
-
-static void __init mvme16x_early_console(void)
-{
- register_console(&cons_info);
-
- printk(KERN_INFO "MVME16x: early console registered\n");
-}
#endif
void __init config_mvme16x(void)
@@ -336,16 +322,6 @@ void __init config_mvme16x(void)
else
{
mvme16x_config = MVME16x_CONFIG_GOT_LP | MVME16x_CONFIG_GOT_CD2401;
-
- /* Dont allow any interrupts from the CD2401 until the interrupt */
- /* handlers are installed */
-
- pcc2chip[PccSCCMICR] = 0x10;
- pcc2chip[PccSCCTICR] = 0x10;
- pcc2chip[PccSCCRICR] = 0x10;
-#ifdef CONFIG_EARLY_PRINTK
- mvme16x_early_console();
-#endif
}
}
diff --git a/arch/metag/include/asm/barrier.h b/arch/metag/include/asm/barrier.h
index 5d6b4b407dda..2d6f0de77325 100644
--- a/arch/metag/include/asm/barrier.h
+++ b/arch/metag/include/asm/barrier.h
@@ -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()
diff --git a/arch/metag/include/asm/processor.h b/arch/metag/include/asm/processor.h
index f16477d1f571..a8a37477c66e 100644
--- a/arch/metag/include/asm/processor.h
+++ b/arch/metag/include/asm/processor.h
@@ -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.
diff --git a/arch/metag/include/uapi/asm/Kbuild b/arch/metag/include/uapi/asm/Kbuild
index 84e09feb4d54..ab78be2b6eb0 100644
--- a/arch/metag/include/uapi/asm/Kbuild
+++ b/arch/metag/include/uapi/asm/Kbuild
@@ -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
index 526d23cc3054..000000000000
--- a/arch/metag/include/uapi/asm/resource.h
+++ /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 */
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 1a5b4032cb66..60a359cfa328 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -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) \
diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c
index c2bb4f896ce7..3aa5b46b2d40 100644
--- a/arch/mips/cavium-octeon/octeon-irq.c
+++ b/arch/mips/cavium-octeon/octeon-irq.c
@@ -635,7 +635,7 @@ static void octeon_irq_cpu_offline_ciu(struct irq_data *data)
cpumask_clear(&new_affinity);
cpumask_set_cpu(cpumask_first(cpu_online_mask), &new_affinity);
}
- __irq_set_affinity_locked(data, &new_affinity);
+ irq_set_affinity_locked(data, &new_affinity, false);
}
static int octeon_irq_ciu_set_affinity(struct irq_data *data,
diff --git a/arch/mips/dec/ecc-berr.c b/arch/mips/dec/ecc-berr.c
index 5abf4e894216..2a66e908f6a9 100644
--- a/arch/mips/dec/ecc-berr.c
+++ b/arch/mips/dec/ecc-berr.c
@@ -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>
diff --git a/arch/mips/dec/kn02xa-berr.c b/arch/mips/dec/kn02xa-berr.c
index f434b759e3b9..ec606363b806 100644
--- a/arch/mips/dec/kn02xa-berr.c
+++ b/arch/mips/dec/kn02xa-berr.c
@@ -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>
diff --git a/arch/mips/dec/prom/Makefile b/arch/mips/dec/prom/Makefile
index 064ae7a76bdc..ae73e42ac20b 100644
--- a/arch/mips/dec/prom/Makefile
+++ b/arch/mips/dec/prom/Makefile
@@ -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
index 8c8498159e43..000000000000
--- a/arch/mips/dec/prom/call_o32.S
+++ /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)
diff --git a/arch/mips/fw/lib/call_o32.S b/arch/mips/fw/lib/call_o32.S
index b308b2a0613e..4703fe4dbd9a 100644
--- a/arch/mips/fw/lib/call_o32.S
+++ b/arch/mips/fw/lib/call_o32.S
@@ -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
@@ -12,28 +12,37 @@
#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)
diff --git a/arch/mips/fw/sni/sniprom.c b/arch/mips/fw/sni/sniprom.c
index 2c2cb182af4e..6aa264b9856a 100644
--- a/arch/mips/fw/sni/sniprom.c
+++ b/arch/mips/fw/sni/sniprom.c
@@ -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); \
diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h
index dc2135be2a3a..ff2707ab3295 100644
--- a/arch/mips/include/asm/cpu-info.h
+++ b/arch/mips/include/asm/cpu-info.h
@@ -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;
diff --git a/arch/mips/include/asm/dec/prom.h b/arch/mips/include/asm/dec/prom.h
index c0ead6313845..b59a2103b61a 100644
--- a/arch/mips/include/asm/dec/prom.h
+++ b/arch/mips/include/asm/dec/prom.h
@@ -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
index b0b80d9ecf96..000000000000
--- a/arch/mips/include/asm/rm9k-ocd.h
+++ /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) */
diff --git a/arch/mips/include/asm/syscall.h b/arch/mips/include/asm/syscall.h
index c6e9cd2bca8d..17960fe7a8ce 100644
--- a/arch/mips/include/asm/syscall.h
+++ b/arch/mips/include/asm/syscall.h
@@ -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;
diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
index df6e775f3fef..3125797f2a88 100644
--- a/arch/mips/include/uapi/asm/inst.h
+++ b/arch/mips/include/uapi/asm/inst.h
@@ -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,
;)))
};
diff --git a/arch/mips/include/uapi/asm/unistd.h b/arch/mips/include/uapi/asm/unistd.h
index d6e154a9e6a5..5805414777e0 100644
--- a/arch/mips/include/uapi/asm/unistd.h
+++ b/arch/mips/include/uapi/asm/unistd.h
@@ -371,16 +371,17 @@
#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
@@ -699,16 +700,17 @@
#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
@@ -1031,15 +1033,16 @@
#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 */
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 4d78bf445a9c..76122ff5cb5e 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -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;
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index e40971b51d2f..037a44d962f3 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -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);
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 71f85f427034..f639ccd5060c 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -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];
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index fdc70b400442..3245474f19d5 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -577,3 +577,4 @@ EXPORT(sys_call_table)
PTR sys_finit_module
PTR sys_sched_setattr
PTR sys_sched_getattr /* 4350 */
+ PTR sys_renameat2
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index dd99c3285aea..be2fedd4ae33 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -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
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index f68d2f4f0090..c1dbcda4b816 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -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
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 70f6acecd928..f1343ccd7ed7 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -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
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 074e857ced28..8119ac2fdfc9 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -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());
diff --git a/arch/mips/lantiq/dts/easy50712.dts b/arch/mips/lantiq/dts/easy50712.dts
index fac1f5b178eb..143b8a37b5e4 100644
--- a/arch/mips/lantiq/dts/easy50712.dts
+++ b/arch/mips/lantiq/dts/easy50712.dts
@@ -8,6 +8,7 @@
};
memory@0 {
+ device_type = "memory";
reg = <0x0 0x2000000>;
};
diff --git a/arch/mips/lib/csum_partial.S b/arch/mips/lib/csum_partial.S
index 2e4825e48388..9901237563c5 100644
--- a/arch/mips/lib/csum_partial.S
+++ b/arch/mips/lib/csum_partial.S
@@ -56,14 +56,20 @@
#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
diff --git a/arch/mips/lib/delay.c b/arch/mips/lib/delay.c
index 44713af15a62..705cfb7c1a74 100644
--- a/arch/mips/lib/delay.c
+++ b/arch/mips/lib/delay.c
@@ -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>
@@ -15,6 +15,12 @@
#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, 1 \n"
+ " subu %0, %1 \n"
#else
- " dsubu %0, 1 \n"
+ " dsubu %0, %1 \n"
#endif
" .set reorder \n"
: "=r" (loops)
- : "0" (loops));
+ : GCC_DADDI_IMM_ASM() (1), "0" (loops));
}
EXPORT_SYMBOL(__delay);
diff --git a/arch/mips/lib/strncpy_user.S b/arch/mips/lib/strncpy_user.S
index d3301cd1e9a5..3c32baf8b494 100644
--- a/arch/mips/lib/strncpy_user.S
+++ b/arch/mips/lib/strncpy_user.S
@@ -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\@
diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig
index 7397be226a06..603d79a95f47 100644
--- a/arch/mips/loongson/Kconfig
+++ b/arch/mips/loongson/Kconfig
@@ -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
diff --git a/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c b/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c
index c639b9db0012..12c75db23420 100644
--- a/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c
+++ b/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c
@@ -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;
}
diff --git a/arch/mips/loongson/lemote-2f/clock.c b/arch/mips/loongson/lemote-2f/clock.c
index e1f427f4f5f3..67dd94ef28e6 100644
--- a/arch/mips/loongson/lemote-2f/clock.c
+++ b/arch/mips/loongson/lemote-2f/clock.c
@@ -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;
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index e422b38d3113..9e67cdea3c74 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -29,15 +29,15 @@ void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start,
void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page,
unsigned long pfn);
void (*flush_icache_range)(unsigned long start, unsigned long end);
+EXPORT_SYMBOL_GPL(flush_icache_range);
void (*local_flush_icache_range)(unsigned long start, unsigned long end);
void (*__flush_cache_vmap)(void);
void (*__flush_cache_vunmap)(void);
void (*__flush_kernel_vmap_range)(unsigned long vaddr, int size);
-void (*__invalidate_kernel_vmap_range)(unsigned long vaddr, int size);
-
EXPORT_SYMBOL_GPL(__flush_kernel_vmap_range);
+void (*__invalidate_kernel_vmap_range)(unsigned long vaddr, int size);
/* MIPS specific cache operations */
void (*flush_cache_sigtramp)(unsigned long addr);
diff --git a/arch/mips/mm/page.c b/arch/mips/mm/page.c
index 58033c44690d..b611102e23b5 100644
--- a/arch/mips/mm/page.c
+++ b/arch/mips/mm/page.c
@@ -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;
diff --git a/arch/mips/mm/tlb-funcs.S b/arch/mips/mm/tlb-funcs.S
index 30a494db99c2..a5427c6e9757 100644
--- a/arch/mips/mm/tlb-funcs.S
+++ b/arch/mips/mm/tlb-funcs.S
@@ -16,8 +16,10 @@
#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)
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index ee88367ab3ad..f99ec587b151 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -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
diff --git a/arch/mips/mti-malta/malta-memory.c b/arch/mips/mti-malta/malta-memory.c
index 6d0f4ab3632d..f2364e419682 100644
--- a/arch/mips/mti-malta/malta-memory.c
+++ b/arch/mips/mti-malta/malta-memory.c
@@ -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;
diff --git a/arch/mips/pci/pci-rc32434.c b/arch/mips/pci/pci-rc32434.c
index b128cb973ebe..7f6ce6d734c0 100644
--- a/arch/mips/pci/pci-rc32434.c
+++ b/arch/mips/pci/pci-rc32434.c
@@ -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
};
diff --git a/arch/mips/ralink/dts/mt7620a_eval.dts b/arch/mips/ralink/dts/mt7620a_eval.dts
index 35eb874ab7f1..709f58132f5c 100644
--- a/arch/mips/ralink/dts/mt7620a_eval.dts
+++ b/arch/mips/ralink/dts/mt7620a_eval.dts
@@ -7,6 +7,7 @@
model = "Ralink MT7620A evaluation board";
memory@0 {
+ device_type = "memory";
reg = <0x0 0x2000000>;
};
diff --git a/arch/mips/ralink/dts/rt2880_eval.dts b/arch/mips/ralink/dts/rt2880_eval.dts
index 322d7002595b..0a685db093d4 100644
--- a/arch/mips/ralink/dts/rt2880_eval.dts
+++ b/arch/mips/ralink/dts/rt2880_eval.dts
@@ -7,6 +7,7 @@
model = "Ralink RT2880 evaluation board";
memory@0 {
+ device_type = "memory";
reg = <0x8000000 0x2000000>;
};
diff --git a/arch/mips/ralink/dts/rt3052_eval.dts b/arch/mips/ralink/dts/rt3052_eval.dts
index 0ac73ea28198..ec9e9a035541 100644
--- a/arch/mips/ralink/dts/rt3052_eval.dts
+++ b/arch/mips/ralink/dts/rt3052_eval.dts
@@ -7,6 +7,7 @@
model = "Ralink RT3052 evaluation board";
memory@0 {
+ device_type = "memory";
reg = <0x0 0x2000000>;
};
diff --git a/arch/mips/ralink/dts/rt3883_eval.dts b/arch/mips/ralink/dts/rt3883_eval.dts
index 2fa6b330bf4f..e8df21a5d10d 100644
--- a/arch/mips/ralink/dts/rt3883_eval.dts
+++ b/arch/mips/ralink/dts/rt3883_eval.dts
@@ -7,6 +7,7 @@
model = "Ralink RT3883 evaluation board";
memory@0 {
+ device_type = "memory";
reg = <0x0 0x2000000>;
};
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 1faefed32749..108d48e652af 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -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
diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h
index 198a86feb574..d951c9681ab3 100644
--- a/arch/parisc/include/asm/processor.h
+++ b/arch/parisc/include/asm/processor.h
@@ -55,6 +55,11 @@
#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__
diff --git a/arch/parisc/include/asm/shmparam.h b/arch/parisc/include/asm/shmparam.h
index 628ddc22faa8..afe1300ab667 100644
--- a/arch/parisc/include/asm/shmparam.h
+++ b/arch/parisc/include/asm/shmparam.h
@@ -1,8 +1,7 @@
#ifndef _ASMPARISC_SHMPARAM_H
#define _ASMPARISC_SHMPARAM_H
-#define __ARCH_FORCE_SHMLBA 1
-
-#define SHMLBA 0x00400000 /* attach addr needs to be 4 Mb aligned */
+#define SHMLBA PAGE_SIZE /* attach addr a multiple of this */
+#define SHM_COLOUR 0x00400000 /* shared mappings colouring */
#endif /* _ASMPARISC_SHMPARAM_H */
diff --git a/arch/parisc/include/uapi/asm/Kbuild b/arch/parisc/include/uapi/asm/Kbuild
index a580642555b6..348356c99514 100644
--- a/arch/parisc/include/uapi/asm/Kbuild
+++ b/arch/parisc/include/uapi/asm/Kbuild
@@ -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
index 8b06343b62ed..000000000000
--- a/arch/parisc/include/uapi/asm/resource.h
+++ /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
diff --git a/arch/parisc/include/uapi/asm/unistd.h b/arch/parisc/include/uapi/asm/unistd.h
index 265ae5190b0a..47e0e21d2272 100644
--- a/arch/parisc/include/uapi/asm/unistd.h
+++ b/arch/parisc/include/uapi/asm/unistd.h
@@ -829,8 +829,9 @@
#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 */
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
index a6ffc775a9f8..f6448c7c62b5 100644
--- a/arch/parisc/kernel/cache.c
+++ b/arch/parisc/kernel/cache.c
@@ -323,7 +323,8 @@ void flush_dcache_page(struct page *page)
* specifically accesses it, of course) */
flush_tlb_page(mpnt, addr);
- if (old_addr == 0 || (old_addr & (SHMLBA - 1)) != (addr & (SHMLBA - 1))) {
+ if (old_addr == 0 || (old_addr & (SHM_COLOUR - 1))
+ != (addr & (SHM_COLOUR - 1))) {
__flush_cache_page(mpnt, addr, page_to_phys(page));
if (old_addr)
printk(KERN_ERR "INEQUIVALENT ALIASES 0x%lx and 0x%lx in file %s\n", old_addr, addr, mpnt->vm_file ? (char *)mpnt->vm_file->f_path.dentry->d_name.name : "(null)");
diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c
index b7cadc4a06cd..e1ffea2f9a0b 100644
--- a/arch/parisc/kernel/sys_parisc.c
+++ b/arch/parisc/kernel/sys_parisc.c
@@ -45,7 +45,7 @@
static int get_offset(unsigned int last_mmap)
{
- return (last_mmap & (SHMLBA-1)) >> PAGE_SHIFT;
+ return (last_mmap & (SHM_COLOUR-1)) >> PAGE_SHIFT;
}
static unsigned long shared_align_offset(unsigned int last_mmap,
@@ -57,8 +57,8 @@ static unsigned long shared_align_offset(unsigned int last_mmap,
static inline unsigned long COLOR_ALIGN(unsigned long addr,
unsigned int last_mmap, unsigned long pgoff)
{
- unsigned long base = (addr+SHMLBA-1) & ~(SHMLBA-1);
- unsigned long off = (SHMLBA-1) &
+ unsigned long base = (addr+SHM_COLOUR-1) & ~(SHM_COLOUR-1);
+ unsigned long off = (SHM_COLOUR-1) &
(shared_align_offset(last_mmap, pgoff) << PAGE_SHIFT);
return base + off;
@@ -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);
}
@@ -101,7 +101,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
if (flags & MAP_FIXED) {
if ((flags & MAP_SHARED) && last_mmap &&
(addr - shared_align_offset(last_mmap, pgoff))
- & (SHMLBA - 1))
+ & (SHM_COLOUR - 1))
return -EINVAL;
goto found_addr;
}
@@ -122,7 +122,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
info.length = len;
info.low_limit = mm->mmap_legacy_base;
info.high_limit = mmap_upper_limit();
- info.align_mask = last_mmap ? (PAGE_MASK & (SHMLBA - 1)) : 0;
+ info.align_mask = last_mmap ? (PAGE_MASK & (SHM_COLOUR - 1)) : 0;
info.align_offset = shared_align_offset(last_mmap, pgoff);
addr = vm_unmapped_area(&info);
@@ -161,7 +161,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
if (flags & MAP_FIXED) {
if ((flags & MAP_SHARED) && last_mmap &&
(addr - shared_align_offset(last_mmap, pgoff))
- & (SHMLBA - 1))
+ & (SHM_COLOUR - 1))
return -EINVAL;
goto found_addr;
}
@@ -182,7 +182,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
info.length = len;
info.low_limit = PAGE_SIZE;
info.high_limit = mm->mmap_base;
- info.align_mask = last_mmap ? (PAGE_MASK & (SHMLBA - 1)) : 0;
+ info.align_mask = last_mmap ? (PAGE_MASK & (SHM_COLOUR - 1)) : 0;
info.align_offset = shared_align_offset(last_mmap, pgoff);
addr = vm_unmapped_area(&info);
if (!(addr & ~PAGE_MASK))
diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S
index a63bb179f79a..838786011037 100644
--- a/arch/parisc/kernel/syscall.S
+++ b/arch/parisc/kernel/syscall.S
@@ -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
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
index 80e5dd248934..c5fa7a697fba 100644
--- a/arch/parisc/kernel/syscall_table.S
+++ b/arch/parisc/kernel/syscall_table.S
@@ -392,7 +392,7 @@
ENTRY_COMP(vmsplice)
ENTRY_COMP(move_pages) /* 295 */
ENTRY_SAME(getcpu)
- ENTRY_SAME(epoll_pwait)
+ ENTRY_COMP(epoll_pwait)
ENTRY_COMP(statfs64)
ENTRY_COMP(fstatfs64)
ENTRY_COMP(kexec_load) /* 300 */
@@ -432,6 +432,7 @@
ENTRY_SAME(sched_setattr)
ENTRY_SAME(sched_getattr) /* 335 */
ENTRY_COMP(utimes)
+ ENTRY_SAME(renameat2)
/* Nothing yet */
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
index 1cd1d0c83b6d..47ee620d15d2 100644
--- a/arch/parisc/kernel/traps.c
+++ b/arch/parisc/kernel/traps.c
@@ -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;
diff --git a/arch/parisc/lib/memcpy.c b/arch/parisc/lib/memcpy.c
index 413dc1769299..b2b441b32341 100644
--- a/arch/parisc/lib/memcpy.c
+++ b/arch/parisc/lib/memcpy.c
@@ -470,7 +470,7 @@ static unsigned long pa_memcpy(void *dstp, const void *srcp, unsigned long len)
return 0;
/* if a load or store fault occured we can get the faulty addr */
- d = &__get_cpu_var(exception_data);
+ d = this_cpu_ptr(&exception_data);
fault_addr = d->fault_addr;
/* error in load or store? */
diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c
index 9d08c71a967e..3ca9c1131cfe 100644
--- a/arch/parisc/mm/fault.c
+++ b/arch/parisc/mm/fault.c
@@ -19,10 +19,6 @@
#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
@@ -151,7 +149,7 @@ int fixup_exception(struct pt_regs *regs)
fix = search_exception_tables(regs->iaoq[0]);
if (fix) {
struct exception_data *d;
- d = &__get_cpu_var(exception_data);
+ d = this_cpu_ptr(&exception_data);
d->fault_ip = regs->iaoq[0];
d->fault_space = regs->isr;
d->fault_addr = regs->ior;
@@ -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 */
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index 4c0cedf4e2c7..ce4c68a4a823 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -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)
diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c
index a28f02165e97..d367a0aece2a 100644
--- a/arch/powerpc/boot/main.c
+++ b/arch/powerpc/boot/main.c
@@ -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();
diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h
index b3218ce451bb..8aad3c55aeda 100644
--- a/arch/powerpc/boot/ops.h
+++ b/arch/powerpc/boot/ops.h
@@ -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? */
diff --git a/arch/powerpc/boot/ps3.c b/arch/powerpc/boot/ps3.c
index 9954d98871d0..4ec2d86d3c50 100644
--- a/arch/powerpc/boot/ps3.c
+++ b/arch/powerpc/boot/ps3.c
@@ -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);
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index a2efdaa020b0..66ad7a74116f 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -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 */
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 6586a40a46ce..cded7c1278ef 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -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) \
diff --git a/arch/powerpc/include/asm/sections.h b/arch/powerpc/include/asm/sections.h
index d0e784e0ff48..521790330672 100644
--- a/arch/powerpc/include/asm/sections.h
+++ b/arch/powerpc/include/asm/sections.h
@@ -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)
{
diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h
index 3ddf70276706..ea4dc3a89c1f 100644
--- a/arch/powerpc/include/asm/systbl.h
+++ b/arch/powerpc/include/asm/systbl.h
@@ -361,3 +361,4 @@ SYSCALL(finit_module)
SYSCALL(ni_syscall) /* sys_kcmp */
SYSCALL_SPU(sched_setattr)
SYSCALL_SPU(sched_getattr)
+SYSCALL_SPU(renameat2)
diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h
index 4494f029b632..9b892bbd9d84 100644
--- a/arch/powerpc/include/asm/unistd.h
+++ b/arch/powerpc/include/asm/unistd.h
@@ -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
diff --git a/arch/powerpc/include/uapi/asm/setup.h b/arch/powerpc/include/uapi/asm/setup.h
index 552df83f1a49..ae3fb68cb28e 100644
--- a/arch/powerpc/include/uapi/asm/setup.h
+++ b/arch/powerpc/include/uapi/asm/setup.h
@@ -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 */
diff --git a/arch/powerpc/include/uapi/asm/unistd.h b/arch/powerpc/include/uapi/asm/unistd.h
index 881bf2e2560d..2d526f7b48da 100644
--- a/arch/powerpc/include/uapi/asm/unistd.h
+++ b/arch/powerpc/include/uapi/asm/unistd.h
@@ -379,5 +379,6 @@
#define __NR_kcmp 354
#define __NR_sched_setattr 355
#define __NR_sched_getattr 356
+#define __NR_renameat2 357
#endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */
diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
index 6a0175297b0d..dd8695f6cb6d 100644
--- a/arch/powerpc/kernel/kvm.c
+++ b/arch/powerpc/kernel/kvm.c
@@ -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)
diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c
index 59d229a2a3e0..879b3aacac32 100644
--- a/arch/powerpc/kernel/machine_kexec_64.c
+++ b/arch/powerpc/kernel/machine_kexec_64.c
@@ -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));
}
}
}
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 2a4779091a58..155013da27e0 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -208,7 +208,7 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus,
unsigned long in_devfn)
{
struct pci_controller* hose;
- struct pci_bus *bus = NULL;
+ struct pci_bus *tmp_bus, *bus = NULL;
struct device_node *hose_node;
/* Argh ! Please forgive me for that hack, but that's the
@@ -229,10 +229,12 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus,
* used on pre-domains setup. We return the first match
*/
- list_for_each_entry(bus, &pci_root_buses, node) {
- if (in_bus >= bus->number && in_bus <= bus->busn_res.end)
+ list_for_each_entry(tmp_bus, &pci_root_buses, node) {
+ if (in_bus >= tmp_bus->number &&
+ in_bus <= tmp_bus->busn_res.end) {
+ bus = tmp_bus;
break;
- bus = NULL;
+ }
}
if (bus == NULL || bus->dev.of_node == NULL)
return -ENODEV;
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index 3bd77edd7610..450850a49dce 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -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
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c
index 2f3cdb01506d..658e89d2025b 100644
--- a/arch/powerpc/kernel/rtas_flash.c
+++ b/arch/powerpc/kernel/rtas_flash.c
@@ -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);
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 122a580f7322..7e711bdcc6da 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -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);
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 94e597e6f15c..7af190a266b3 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -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
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
index 1d6c56ad5b60..8fcc36306a02 100644
--- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c
+++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
@@ -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);
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index ffbb871c2bd8..07c8b5b0f9d2 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -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
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
index c5c052a9729c..02f1defd8bb9 100644
--- a/arch/powerpc/kvm/book3s_pr.c
+++ b/arch/powerpc/kvm/book3s_pr.c
@@ -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);
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index 3ea26c25590b..cf1d325eae8b 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -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");
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index d766d6ee33fe..06ba83b036d3 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -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
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 4ebbb9e99286..3b181b22cd46 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -232,6 +232,7 @@ int __node_distance(int a, int b)
return distance;
}
+EXPORT_SYMBOL(__node_distance);
static void initialize_distance_lookup_table(int nid,
const __be32 *associativity)
diff --git a/arch/powerpc/perf/hv-24x7.c b/arch/powerpc/perf/hv-24x7.c
index 297c91051413..e0766b82e165 100644
--- a/arch/powerpc/perf/hv-24x7.c
+++ b/arch/powerpc/perf/hv-24x7.c
@@ -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;
}
diff --git a/arch/powerpc/perf/hv-gpci.c b/arch/powerpc/perf/hv-gpci.c
index 278ba7b9c2b5..c9d399a2df82 100644
--- a/arch/powerpc/perf/hv-gpci.c
+++ b/arch/powerpc/perf/hv-gpci.c
@@ -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;
}
diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c
index 253fefe3d1a0..5b51079f3e3b 100644
--- a/arch/powerpc/platforms/powernv/eeh-ioda.c
+++ b/arch/powerpc/platforms/powernv/eeh-ioda.c
@@ -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);
diff --git a/arch/powerpc/platforms/powernv/opal-dump.c b/arch/powerpc/platforms/powernv/opal-dump.c
index b9827b0d87e4..788a1977b9a5 100644
--- a/arch/powerpc/platforms/powernv/opal-dump.c
+++ b/arch/powerpc/platforms/powernv/opal-dump.c
@@ -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;
diff --git a/arch/powerpc/platforms/powernv/opal-elog.c b/arch/powerpc/platforms/powernv/opal-elog.c
index ef7bc2a97862..10268c41d830 100644
--- a/arch/powerpc/platforms/powernv/opal-elog.c
+++ b/arch/powerpc/platforms/powernv/opal-elog.c
@@ -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)
diff --git a/arch/powerpc/platforms/powernv/opal-flash.c b/arch/powerpc/platforms/powernv/opal-flash.c
index 714ef972406b..dc487ff04704 100644
--- a/arch/powerpc/platforms/powernv/opal-flash.c
+++ b/arch/powerpc/platforms/powernv/opal-flash.c
@@ -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);
}
/*
@@ -268,93 +269,11 @@ static ssize_t manage_store(struct kobject *kobj,
}
/*
- * 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");
diff --git a/arch/powerpc/platforms/powernv/opal-sysparam.c b/arch/powerpc/platforms/powernv/opal-sysparam.c
index 6b614726baf2..d202f9bc3683 100644
--- a/arch/powerpc/platforms/powernv/opal-sysparam.c
+++ b/arch/powerpc/platforms/powernv/opal-sysparam.c
@@ -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];
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 49d2f00019e5..360ad80c754c 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -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;
+ }
+}
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index 3b2b4fb3585b..98824aa99173 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -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,
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
index 61cf8fa9c61b..8723d32632f5 100644
--- a/arch/powerpc/platforms/powernv/setup.c
+++ b/arch/powerpc/platforms/powernv/setup.c
@@ -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 */
diff --git a/arch/powerpc/platforms/powernv/smp.c b/arch/powerpc/platforms/powernv/smp.c
index 908672bdcea6..bf5fcd452168 100644
--- a/arch/powerpc/platforms/powernv/smp.c
+++ b/arch/powerpc/platforms/powernv/smp.c
@@ -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
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
index 9b8e05078a63..20d62975856f 100644
--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -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);
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
index 573b488fc48b..7f75c94af822 100644
--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
+++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
@@ -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;
}
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c
index 64603a10b863..4914fd3f41ec 100644
--- a/arch/powerpc/sysdev/ppc4xx_pci.c
+++ b/arch/powerpc/sysdev/ppc4xx_pci.c
@@ -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;
diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c
index cf3c0089bef2..23223cd63e54 100644
--- a/arch/s390/crypto/aes_s390.c
+++ b/arch/s390/crypto/aes_s390.c
@@ -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
diff --git a/arch/s390/crypto/des_s390.c b/arch/s390/crypto/des_s390.c
index 0a5aac8a9412..7acb77f7ef1a 100644
--- a/arch/s390/crypto/des_s390.c
+++ b/arch/s390/crypto/des_s390.c
@@ -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) {
diff --git a/arch/s390/include/asm/ccwgroup.h b/arch/s390/include/asm/ccwgroup.h
index 6e670f88d125..ebc2913f9ee0 100644
--- a/arch/s390/include/asm/ccwgroup.h
+++ b/arch/s390/include/asm/ccwgroup.h
@@ -22,8 +22,8 @@ struct ccwgroup_device {
/* public: */
unsigned int count;
struct device dev;
- struct ccw_device *cdev[0];
struct work_struct ungroup_work;
+ struct ccw_device *cdev[0];
};
/**
diff --git a/arch/s390/include/asm/sigp.h b/arch/s390/include/asm/sigp.h
index d091aa1aaf11..bf9c823d4020 100644
--- a/arch/s390/include/asm/sigp.h
+++ b/arch/s390/include/asm/sigp.h
@@ -31,4 +31,23 @@
#define SIGP_STATUS_INCORRECT_STATE 0x00000200UL
#define SIGP_STATUS_NOT_RUNNING 0x00000400UL
+#ifndef __ASSEMBLY__
+
+static inline int __pcpu_sigp(u16 addr, u8 order, u32 parm, u32 *status)
+{
+ register unsigned int reg1 asm ("1") = parm;
+ int cc;
+
+ asm volatile(
+ " sigp %1,%2,0(%3)\n"
+ " ipm %0\n"
+ " srl %0,28\n"
+ : "=d" (cc), "+d" (reg1) : "d" (addr), "a" (order) : "cc");
+ if (status && cc == 1)
+ *status = reg1;
+ return cc;
+}
+
+#endif /* __ASSEMBLY__ */
+
#endif /* __S390_ASM_SIGP_H */
diff --git a/arch/s390/include/asm/smp.h b/arch/s390/include/asm/smp.h
index 160779394096..21703f85b48d 100644
--- a/arch/s390/include/asm/smp.h
+++ b/arch/s390/include/asm/smp.h
@@ -7,6 +7,8 @@
#ifndef __ASM_SMP_H
#define __ASM_SMP_H
+#include <asm/sigp.h>
+
#ifdef CONFIG_SMP
#include <asm/lowcore.h>
@@ -50,9 +52,18 @@ static inline int smp_store_status(int cpu) { return 0; }
static inline int smp_vcpu_scheduled(int cpu) { return 1; }
static inline void smp_yield_cpu(int cpu) { }
static inline void smp_yield(void) { }
-static inline void smp_stop_cpu(void) { }
static inline void smp_fill_possible_mask(void) { }
+static inline void smp_stop_cpu(void)
+{
+ u16 pcpu = stap();
+
+ for (;;) {
+ __pcpu_sigp(pcpu, SIGP_STOP, 0, NULL);
+ cpu_relax();
+ }
+}
+
#endif /* CONFIG_SMP */
#ifdef CONFIG_HOTPLUG_CPU
diff --git a/arch/s390/include/asm/tlb.h b/arch/s390/include/asm/tlb.h
index c544b6f05d95..a25f09fbaf36 100644
--- a/arch/s390/include/asm/tlb.h
+++ b/arch/s390/include/asm/tlb.h
@@ -59,12 +59,23 @@ static inline void tlb_gather_mmu(struct mmu_gather *tlb,
tlb->batch = NULL;
}
-static inline void tlb_flush_mmu(struct mmu_gather *tlb)
+static inline void tlb_flush_mmu_tlbonly(struct mmu_gather *tlb)
{
__tlb_flush_mm_lazy(tlb->mm);
+}
+
+static inline void tlb_flush_mmu_free(struct mmu_gather *tlb)
+{
tlb_table_flush(tlb);
}
+
+static inline void tlb_flush_mmu(struct mmu_gather *tlb)
+{
+ tlb_flush_mmu_tlbonly(tlb);
+ tlb_flush_mmu_free(tlb);
+}
+
static inline void tlb_finish_mmu(struct mmu_gather *tlb,
unsigned long start, unsigned long end)
{
diff --git a/arch/s390/include/uapi/asm/unistd.h b/arch/s390/include/uapi/asm/unistd.h
index 5eb5c9ddb120..3802d2d3a18d 100644
--- a/arch/s390/include/uapi/asm/unistd.h
+++ b/arch/s390/include/uapi/asm/unistd.h
@@ -282,7 +282,8 @@
#define __NR_finit_module 344
#define __NR_sched_setattr 345
#define __NR_sched_getattr 346
-#define NR_syscalls 345
+#define __NR_renameat2 347
+#define NR_syscalls 348
/*
* There are some system calls that are not present on 64 bit, some
diff --git a/arch/s390/kernel/compat_wrapper.c b/arch/s390/kernel/compat_wrapper.c
index 824c39dfddfc..45cdb37aa6f8 100644
--- a/arch/s390/kernel/compat_wrapper.c
+++ b/arch/s390/kernel/compat_wrapper.c
@@ -1,5 +1,5 @@
/*
- * Compat sytem call wrappers.
+ * Compat system call wrappers.
*
* Copyright IBM Corp. 2014
*/
@@ -213,3 +213,4 @@ COMPAT_SYSCALL_WRAP5(kcmp, pid_t, pid1, pid_t, pid2, int, type, unsigned long, i
COMPAT_SYSCALL_WRAP3(finit_module, int, fd, const char __user *, uargs, int, flags);
COMPAT_SYSCALL_WRAP3(sched_setattr, pid_t, pid, struct sched_attr __user *, attr, unsigned int, flags);
COMPAT_SYSCALL_WRAP4(sched_getattr, pid_t, pid, struct sched_attr __user *, attr, unsigned int, size, unsigned int, flags);
+COMPAT_SYSCALL_WRAP5(renameat2, int, olddfd, const char __user *, oldname, int, newdfd, const char __user *, newname, unsigned int, flags);
diff --git a/arch/s390/kernel/dumpstack.c b/arch/s390/kernel/dumpstack.c
index e6af9406987c..acb412442e5e 100644
--- a/arch/s390/kernel/dumpstack.c
+++ b/arch/s390/kernel/dumpstack.c
@@ -144,10 +144,10 @@ void show_registers(struct pt_regs *regs)
char *mode;
mode = user_mode(regs) ? "User" : "Krnl";
- printk("%s PSW : %p %p (%pSR)\n",
- mode, (void *) regs->psw.mask,
- (void *) regs->psw.addr,
- (void *) regs->psw.addr);
+ printk("%s PSW : %p %p", mode, (void *)regs->psw.mask, (void *)regs->psw.addr);
+ if (!user_mode(regs))
+ printk(" (%pSR)", (void *)regs->psw.addr);
+ printk("\n");
printk(" R:%x T:%x IO:%x EX:%x Key:%x M:%x W:%x "
"P:%x AS:%x CC:%x PM:%x", mask_bits(regs, PSW_MASK_PER),
mask_bits(regs, PSW_MASK_DAT), mask_bits(regs, PSW_MASK_IO),
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index 4ac8fafec95f..1c82619eb4f7 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -64,7 +64,7 @@ void update_cr_regs(struct task_struct *task)
if (task->thread.per_flags & PER_FLAG_NO_TE)
cr_new &= ~(1UL << 55);
if (cr_new != cr)
- __ctl_load(cr, 0, 0);
+ __ctl_load(cr_new, 0, 0);
/* Set or clear transaction execution TDC bits 62 and 63. */
__ctl_store(cr, 2, 2);
cr_new = cr & ~3UL;
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index f70f2489fa5f..88d1ca81e2dd 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -1027,3 +1027,35 @@ void __init setup_arch(char **cmdline_p)
/* Setup zfcpdump support */
setup_zfcpdump();
}
+
+#ifdef CONFIG_32BIT
+static int no_removal_warning __initdata;
+
+static int __init parse_no_removal_warning(char *str)
+{
+ no_removal_warning = 1;
+ return 0;
+}
+__setup("no_removal_warning", parse_no_removal_warning);
+
+static int __init removal_warning(void)
+{
+ if (no_removal_warning)
+ return 0;
+ printk(KERN_ALERT "\n\n");
+ printk(KERN_CONT "Warning - you are using a 31 bit kernel!\n\n");
+ printk(KERN_CONT "We plan to remove 31 bit kernel support from the kernel sources in March 2015.\n");
+ printk(KERN_CONT "Currently we assume that nobody is using the 31 bit kernel on old 31 bit\n");
+ printk(KERN_CONT "hardware anymore. If you think that the code should not be removed and also\n");
+ printk(KERN_CONT "future versions of the Linux kernel should be able to run in 31 bit mode\n");
+ printk(KERN_CONT "please let us know. Please write to:\n");
+ printk(KERN_CONT "linux390@de.ibm.com (mail address) and/or\n");
+ printk(KERN_CONT "linux-s390@vger.kernel.org (mailing list).\n\n");
+ printk(KERN_CONT "Thank you!\n\n");
+ printk(KERN_CONT "If this kernel runs on a 64 bit machine you may consider using a 64 bit kernel.\n");
+ printk(KERN_CONT "This message can be disabled with the \"no_removal_warning\" kernel parameter.\n");
+ schedule_timeout_uninterruptible(300 * HZ);
+ return 0;
+}
+early_initcall(removal_warning);
+#endif
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 512ce1cde2a4..86e65ec3422b 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -82,21 +82,6 @@ DEFINE_MUTEX(smp_cpu_state_mutex);
/*
* Signal processor helper functions.
*/
-static inline int __pcpu_sigp(u16 addr, u8 order, u32 parm, u32 *status)
-{
- register unsigned int reg1 asm ("1") = parm;
- int cc;
-
- asm volatile(
- " sigp %1,%2,0(%3)\n"
- " ipm %0\n"
- " srl %0,28\n"
- : "=d" (cc), "+d" (reg1) : "d" (addr), "a" (order) : "cc");
- if (status && cc == 1)
- *status = reg1;
- return cc;
-}
-
static inline int __pcpu_sigp_relax(u16 addr, u8 order, u32 parm, u32 *status)
{
int cc;
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index 542ef488bac1..fe5cdf29a001 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -355,3 +355,4 @@ SYSCALL(sys_kcmp,sys_kcmp,compat_sys_kcmp)
SYSCALL(sys_finit_module,sys_finit_module,compat_sys_finit_module)
SYSCALL(sys_sched_setattr,sys_sched_setattr,compat_sys_sched_setattr) /* 345 */
SYSCALL(sys_sched_getattr,sys_sched_getattr,compat_sys_sched_getattr)
+SYSCALL(sys_renameat2,sys_renameat2,compat_sys_renameat2)
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index b3ecb8f5b6ce..9ae6664ff08c 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -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:
diff --git a/arch/s390/lib/uaccess.c b/arch/s390/lib/uaccess.c
index 23f866b4c7f1..7416efe8eae4 100644
--- a/arch/s390/lib/uaccess.c
+++ b/arch/s390/lib/uaccess.c
@@ -338,9 +338,6 @@ static inline unsigned long strnlen_user_srst(const char __user *src,
register unsigned long reg0 asm("0") = 0;
unsigned long tmp1, tmp2;
- if (unlikely(!size))
- return 0;
- update_primary_asce(current);
asm volatile(
" la %2,0(%1)\n"
" la %3,0(%0,%1)\n"
@@ -359,6 +356,8 @@ static inline unsigned long strnlen_user_srst(const char __user *src,
unsigned long __strnlen_user(const char __user *src, unsigned long size)
{
+ if (unlikely(!size))
+ return 0;
update_primary_asce(current);
return strnlen_user_srst(src, size);
}
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 19f623f1f21c..2f51a998a67e 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -126,6 +126,133 @@ static inline int user_space_fault(struct pt_regs *regs)
return 0;
}
+static int bad_address(void *p)
+{
+ unsigned long dummy;
+
+ return probe_kernel_address((unsigned long *)p, dummy);
+}
+
+#ifdef CONFIG_64BIT
+static void dump_pagetable(unsigned long asce, unsigned long address)
+{
+ unsigned long *table = __va(asce & PAGE_MASK);
+
+ pr_alert("AS:%016lx ", asce);
+ switch (asce & _ASCE_TYPE_MASK) {
+ case _ASCE_TYPE_REGION1:
+ table = table + ((address >> 53) & 0x7ff);
+ if (bad_address(table))
+ goto bad;
+ pr_cont("R1:%016lx ", *table);
+ if (*table & _REGION_ENTRY_INVALID)
+ goto out;
+ table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+ /* fallthrough */
+ case _ASCE_TYPE_REGION2:
+ table = table + ((address >> 42) & 0x7ff);
+ if (bad_address(table))
+ goto bad;
+ pr_cont("R2:%016lx ", *table);
+ if (*table & _REGION_ENTRY_INVALID)
+ goto out;
+ table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+ /* fallthrough */
+ case _ASCE_TYPE_REGION3:
+ table = table + ((address >> 31) & 0x7ff);
+ if (bad_address(table))
+ goto bad;
+ pr_cont("R3:%016lx ", *table);
+ if (*table & (_REGION_ENTRY_INVALID | _REGION3_ENTRY_LARGE))
+ goto out;
+ table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+ /* fallthrough */
+ case _ASCE_TYPE_SEGMENT:
+ table = table + ((address >> 20) & 0x7ff);
+ if (bad_address(table))
+ goto bad;
+ pr_cont(KERN_CONT "S:%016lx ", *table);
+ if (*table & (_SEGMENT_ENTRY_INVALID | _SEGMENT_ENTRY_LARGE))
+ goto out;
+ table = (unsigned long *)(*table & _SEGMENT_ENTRY_ORIGIN);
+ }
+ table = table + ((address >> 12) & 0xff);
+ if (bad_address(table))
+ goto bad;
+ pr_cont("P:%016lx ", *table);
+out:
+ pr_cont("\n");
+ return;
+bad:
+ pr_cont("BAD\n");
+}
+
+#else /* CONFIG_64BIT */
+
+static void dump_pagetable(unsigned long asce, unsigned long address)
+{
+ unsigned long *table = __va(asce & PAGE_MASK);
+
+ pr_alert("AS:%08lx ", asce);
+ table = table + ((address >> 20) & 0x7ff);
+ if (bad_address(table))
+ goto bad;
+ pr_cont("S:%08lx ", *table);
+ if (*table & _SEGMENT_ENTRY_INVALID)
+ goto out;
+ table = (unsigned long *)(*table & _SEGMENT_ENTRY_ORIGIN);
+ table = table + ((address >> 12) & 0xff);
+ if (bad_address(table))
+ goto bad;
+ pr_cont("P:%08lx ", *table);
+out:
+ pr_cont("\n");
+ return;
+bad:
+ pr_cont("BAD\n");
+}
+
+#endif /* CONFIG_64BIT */
+
+static void dump_fault_info(struct pt_regs *regs)
+{
+ unsigned long asce;
+
+ pr_alert("Fault in ");
+ switch (regs->int_parm_long & 3) {
+ case 3:
+ pr_cont("home space ");
+ break;
+ case 2:
+ pr_cont("secondary space ");
+ break;
+ case 1:
+ pr_cont("access register ");
+ break;
+ case 0:
+ pr_cont("primary space ");
+ break;
+ }
+ pr_cont("mode while using ");
+ if (!user_space_fault(regs)) {
+ asce = S390_lowcore.kernel_asce;
+ pr_cont("kernel ");
+ }
+#ifdef CONFIG_PGSTE
+ else if ((current->flags & PF_VCPU) && S390_lowcore.gmap) {
+ struct gmap *gmap = (struct gmap *)S390_lowcore.gmap;
+ asce = gmap->asce;
+ pr_cont("gmap ");
+ }
+#endif
+ else {
+ asce = S390_lowcore.user_asce;
+ pr_cont("user ");
+ }
+ pr_cont("ASCE.\n");
+ dump_pagetable(asce, regs->int_parm_long & __FAIL_ADDR_MASK);
+}
+
static inline void report_user_fault(struct pt_regs *regs, long signr)
{
if ((task_pid_nr(current) > 1) && !show_unhandled_signals)
@@ -138,8 +265,9 @@ static inline void report_user_fault(struct pt_regs *regs, long signr)
regs->int_code);
print_vma_addr(KERN_CONT "in ", regs->psw.addr & PSW_ADDR_INSN);
printk(KERN_CONT "\n");
- printk(KERN_ALERT "failing address: %lX\n",
- regs->int_parm_long & __FAIL_ADDR_MASK);
+ printk(KERN_ALERT "failing address: %016lx TEID: %016lx\n",
+ regs->int_parm_long & __FAIL_ADDR_MASK, regs->int_parm_long);
+ dump_fault_info(regs);
show_regs(regs);
}
@@ -177,11 +305,13 @@ static noinline void do_no_context(struct pt_regs *regs)
address = regs->int_parm_long & __FAIL_ADDR_MASK;
if (!user_space_fault(regs))
printk(KERN_ALERT "Unable to handle kernel pointer dereference"
- " at virtual kernel address %p\n", (void *)address);
+ " in virtual kernel address space\n");
else
printk(KERN_ALERT "Unable to handle kernel paging request"
- " at virtual user address %p\n", (void *)address);
-
+ " in virtual user address space\n");
+ printk(KERN_ALERT "failing address: %016lx TEID: %016lx\n",
+ regs->int_parm_long & __FAIL_ADDR_MASK, regs->int_parm_long);
+ dump_fault_info(regs);
die(regs, "Oops");
do_exit(SIGKILL);
}
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
index 9c36dc398f90..e9f8fa9337fe 100644
--- a/arch/s390/net/bpf_jit_comp.c
+++ b/arch/s390/net/bpf_jit_comp.c
@@ -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.
*/
diff --git a/arch/sh/include/asm/tlb.h b/arch/sh/include/asm/tlb.h
index 362192ed12fe..62f80d2a9df9 100644
--- a/arch/sh/include/asm/tlb.h
+++ b/arch/sh/include/asm/tlb.h
@@ -86,6 +86,14 @@ tlb_end_vma(struct mmu_gather *tlb, struct vm_area_struct *vma)
}
}
+static inline void tlb_flush_mmu_tlbonly(struct mmu_gather *tlb)
+{
+}
+
+static inline void tlb_flush_mmu_free(struct mmu_gather *tlb)
+{
+}
+
static inline void tlb_flush_mmu(struct mmu_gather *tlb)
{
}
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
index 0f9e94537eee..1a49ffdf9da9 100644
--- a/arch/sparc/include/asm/pgtable_64.h
+++ b/arch/sparc/include/asm/pgtable_64.h
@@ -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)
@@ -71,6 +73,23 @@
#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)
@@ -79,9 +98,12 @@
/* 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);
/*
diff --git a/arch/sparc/include/asm/tsb.h b/arch/sparc/include/asm/tsb.h
index 2230f80d9fe3..90916f955cac 100644
--- a/arch/sparc/include/asm/tsb.h
+++ b/arch/sparc/include/asm/tsb.h
@@ -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; \
diff --git a/arch/sparc/kernel/head_64.S b/arch/sparc/kernel/head_64.S
index 26b706a1867d..452f04fe8da6 100644
--- a/arch/sparc/kernel/head_64.S
+++ b/arch/sparc/kernel/head_64.S
@@ -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" */
diff --git a/arch/sparc/kernel/ktlb.S b/arch/sparc/kernel/ktlb.S
index 542e96ac4d39..605d49204580 100644
--- a/arch/sparc/kernel/ktlb.S
+++ b/arch/sparc/kernel/ktlb.S
@@ -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
diff --git a/arch/sparc/kernel/nmi.c b/arch/sparc/kernel/nmi.c
index 6479256fd5a4..337094556916 100644
--- a/arch/sparc/kernel/nmi.c
+++ b/arch/sparc/kernel/nmi.c
@@ -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)
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c
index 9781048161ab..745a3633ce14 100644
--- a/arch/sparc/kernel/smp_64.c
+++ b/arch/sparc/kernel/smp_64.c
@@ -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)
diff --git a/arch/sparc/kernel/sys32.S b/arch/sparc/kernel/sys32.S
index f7c72b6efc27..d066eb18650c 100644
--- a/arch/sparc/kernel/sys32.S
+++ b/arch/sparc/kernel/sys32.S
@@ -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)
diff --git a/arch/sparc/kernel/sysfs.c b/arch/sparc/kernel/sysfs.c
index a364000ca1aa..7f41d40b7e6e 100644
--- a/arch/sparc/kernel/sysfs.c
+++ b/arch/sparc/kernel/sysfs.c
@@ -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;
diff --git a/arch/sparc/kernel/unaligned_64.c b/arch/sparc/kernel/unaligned_64.c
index 3c1a7cb31579..35ab8b60d256 100644
--- a/arch/sparc/kernel/unaligned_64.c
+++ b/arch/sparc/kernel/unaligned_64.c
@@ -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... */
diff --git a/arch/sparc/lib/NG2memcpy.S b/arch/sparc/lib/NG2memcpy.S
index 2c20ad63ddbf..30eee6e8a81b 100644
--- a/arch/sparc/lib/NG2memcpy.S
+++ b/arch/sparc/lib/NG2memcpy.S
@@ -236,6 +236,7 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */
*/
VISEntryHalf
+ membar #Sync
alignaddr %o1, %g0, %g0
add %o1, (64 - 1), %o4
diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c
index 69bb818fdd79..4ced3fc66130 100644
--- a/arch/sparc/mm/fault_64.c
+++ b/arch/sparc/mm/fault_64.c
@@ -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)
diff --git a/arch/sparc/mm/gup.c b/arch/sparc/mm/gup.c
index c4d3da68b800..1aed0432c64b 100644
--- a/arch/sparc/mm/gup.c
+++ b/arch/sparc/mm/gup.c
@@ -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))
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index eafbc65c9c47..ed3c969a5f4c 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -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;
diff --git a/arch/sparc/mm/tlb.c b/arch/sparc/mm/tlb.c
index b12cb5e72812..b89aba217e3b 100644
--- a/arch/sparc/mm/tlb.c
+++ b/arch/sparc/mm/tlb.c
@@ -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)
{
diff --git a/arch/sparc/mm/tsb.c b/arch/sparc/mm/tsb.c
index f5d506fdddad..fe19b81acc09 100644
--- a/arch/sparc/mm/tsb.c
+++ b/arch/sparc/mm/tsb.c
@@ -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));
diff --git a/arch/um/include/asm/tlb.h b/arch/um/include/asm/tlb.h
index 29b0301c18aa..16eb63fac57d 100644
--- a/arch/um/include/asm/tlb.h
+++ b/arch/um/include/asm/tlb.h
@@ -59,13 +59,25 @@ extern void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
unsigned long end);
static inline void
+tlb_flush_mmu_tlbonly(struct mmu_gather *tlb)
+{
+ flush_tlb_mm_range(tlb->mm, tlb->start, tlb->end);
+}
+
+static inline void
+tlb_flush_mmu_free(struct mmu_gather *tlb)
+{
+ init_tlb_gather(tlb);
+}
+
+static inline void
tlb_flush_mmu(struct mmu_gather *tlb)
{
if (!tlb->need_flush)
return;
- flush_tlb_mm_range(tlb->mm, tlb->start, tlb->end);
- init_tlb_gather(tlb);
+ tlb_flush_mmu_tlbonly(tlb);
+ tlb_flush_mmu_free(tlb);
}
/* tlb_finish_mmu
diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h
index 75298d3358e7..08eec0b691b0 100644
--- a/arch/um/include/shared/os.h
+++ b/arch/um/include/shared/os.h
@@ -136,6 +136,7 @@ extern int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg);
extern int os_get_ifname(int fd, char *namebuf);
extern int os_set_slip(int fd);
extern int os_mode_fd(int fd, int mode);
+extern int os_fsync_file(int fd);
extern int os_seek_file(int fd, unsigned long long offset);
extern int os_open_file(const char *file, struct openflags flags, int mode);
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
index f116db15d402..30fdd5d0067b 100644
--- a/arch/um/kernel/physmem.c
+++ b/arch/um/kernel/physmem.c
@@ -103,6 +103,7 @@ void __init setup_physmem(unsigned long start, unsigned long reserve_end,
*/
os_seek_file(physmem_fd, __pa(&__syscall_stub_start));
os_write_file(physmem_fd, &__syscall_stub_start, PAGE_SIZE);
+ os_fsync_file(physmem_fd);
bootmap_size = init_bootmem(pfn, pfn + delta);
free_bootmem(__pa(reserve_end) + bootmap_size,
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
index 07a750197bb0..08d90fba952c 100644
--- a/arch/um/os-Linux/file.c
+++ b/arch/um/os-Linux/file.c
@@ -237,6 +237,12 @@ void os_close_file(int fd)
{
close(fd);
}
+int os_fsync_file(int fd)
+{
+ if (fsync(fd) < 0)
+ return -errno;
+ return 0;
+}
int os_seek_file(int fd, unsigned long long offset)
{
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index e1704ff600ff..df9191acd926 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -151,6 +151,7 @@ int __init main(int argc, char **argv, char **envp)
#endif
do_uml_initcalls();
+ change_sig(SIGPIPE, 0);
ret = linux_main(argc, argv);
/*
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index 3c4af77e51a2..897e9ad0c108 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -12,337 +12,117 @@
#include <string.h>
#include <sys/stat.h>
#include <sys/mman.h>
-#include <sys/param.h>
+#include <sys/vfs.h>
+#include <linux/magic.h>
#include <init.h>
#include <os.h>
-/* Modified by which_tmpdir, which is called during early boot */
-static char *default_tmpdir = "/tmp";
-
-/*
- * Modified when creating the physical memory file and when checking
- * the tmp filesystem for usability, both happening during early boot.
- */
+/* Set by make_tempfile() during early boot. */
static char *tempdir = NULL;
-static void __init find_tempdir(void)
+/* Check if dir is on tmpfs. Return 0 if yes, -1 if no or error. */
+static int __init check_tmpfs(const char *dir)
{
- const char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL };
- int i;
- char *dir = NULL;
-
- if (tempdir != NULL)
- /* We've already been called */
- return;
- for (i = 0; dirs[i]; i++) {
- dir = getenv(dirs[i]);
- if ((dir != NULL) && (*dir != '\0'))
- break;
- }
- if ((dir == NULL) || (*dir == '\0'))
- dir = default_tmpdir;
+ struct statfs st;
- tempdir = malloc(strlen(dir) + 2);
- if (tempdir == NULL) {
- fprintf(stderr, "Failed to malloc tempdir, "
- "errno = %d\n", errno);
- return;
- }
- strcpy(tempdir, dir);
- strcat(tempdir, "/");
-}
-
-/*
- * Remove bytes from the front of the buffer and refill it so that if there's a
- * partial string that we care about, it will be completed, and we can recognize
- * it.
- */
-static int pop(int fd, char *buf, size_t size, size_t npop)
-{
- ssize_t n;
- size_t len = strlen(&buf[npop]);
-
- memmove(buf, &buf[npop], len + 1);
- n = read(fd, &buf[len], size - len - 1);
- if (n < 0)
- return -errno;
-
- buf[len + n] = '\0';
- return 1;
-}
-
-/*
- * This will return 1, with the first character in buf being the
- * character following the next instance of c in the file. This will
- * read the file as needed. If there's an error, -errno is returned;
- * if the end of the file is reached, 0 is returned.
- */
-static int next(int fd, char *buf, size_t size, char c)
-{
- ssize_t n;
- char *ptr;
-
- while ((ptr = strchr(buf, c)) == NULL) {
- n = read(fd, buf, size - 1);
- if (n == 0)
- return 0;
- else if (n < 0)
- return -errno;
-
- buf[n] = '\0';
+ printf("Checking if %s is on tmpfs...", dir);
+ if (statfs(dir, &st) < 0) {
+ printf("%s\n", strerror(errno));
+ } else if (st.f_type != TMPFS_MAGIC) {
+ printf("no\n");
+ } else {
+ printf("OK\n");
+ return 0;
}
-
- return pop(fd, buf, size, ptr - buf + 1);
+ return -1;
}
/*
- * Decode an octal-escaped and space-terminated path of the form used by
- * /proc/mounts. May be used to decode a path in-place. "out" must be at least
- * as large as the input. The output is always null-terminated. "len" gets the
- * length of the output, excluding the trailing null. Returns 0 if a full path
- * was successfully decoded, otherwise an error.
+ * Choose the tempdir to use. We want something on tmpfs so that our memory is
+ * not subject to the host's vm.dirty_ratio. If a tempdir is specified in the
+ * environment, we use that even if it's not on tmpfs, but we warn the user.
+ * Otherwise, we try common tmpfs locations, and if no tmpfs directory is found
+ * then we fall back to /tmp.
*/
-static int decode_path(const char *in, char *out, size_t *len)
+static char * __init choose_tempdir(void)
{
- char *first = out;
- int c;
+ static const char * const vars[] = {
+ "TMPDIR",
+ "TMP",
+ "TEMP",
+ NULL
+ };
+ static const char fallback_dir[] = "/tmp";
+ static const char * const tmpfs_dirs[] = {
+ "/dev/shm",
+ fallback_dir,
+ NULL
+ };
int i;
- int ret = -EINVAL;
- while (1) {
- switch (*in) {
- case '\0':
- goto out;
-
- case ' ':
- ret = 0;
- goto out;
-
- case '\\':
- in++;
- c = 0;
- for (i = 0; i < 3; i++) {
- if (*in < '0' || *in > '7')
- goto out;
- c = (c << 3) | (*in++ - '0');
- }
- *(unsigned char *)out++ = (unsigned char) c;
- break;
-
- default:
- *out++ = *in++;
- break;
+ const char *dir;
+
+ printf("Checking environment variables for a tempdir...");
+ for (i = 0; vars[i]; i++) {
+ dir = getenv(vars[i]);
+ if ((dir != NULL) && (*dir != '\0')) {
+ printf("%s\n", dir);
+ if (check_tmpfs(dir) >= 0)
+ goto done;
+ else
+ goto warn;
}
}
+ printf("none found\n");
-out:
- *out = '\0';
- *len = out - first;
- return ret;
-}
-
-/*
- * Computes the length of s when encoded with three-digit octal escape sequences
- * for the characters in chars.
- */
-static size_t octal_encoded_length(const char *s, const char *chars)
-{
- size_t len = strlen(s);
- while ((s = strpbrk(s, chars)) != NULL) {
- len += 3;
- s++;
- }
-
- return len;
-}
-
-enum {
- OUTCOME_NOTHING_MOUNTED,
- OUTCOME_TMPFS_MOUNT,
- OUTCOME_NON_TMPFS_MOUNT,
-};
-
-/* Read a line of /proc/mounts data looking for a tmpfs mount at "path". */
-static int read_mount(int fd, char *buf, size_t bufsize, const char *path,
- int *outcome)
-{
- int found;
- int match;
- char *space;
- size_t len;
-
- enum {
- MATCH_NONE,
- MATCH_EXACT,
- MATCH_PARENT,
- };
-
- found = next(fd, buf, bufsize, ' ');
- if (found != 1)
- return found;
-
- /*
- * If there's no following space in the buffer, then this path is
- * truncated, so it can't be the one we're looking for.
- */
- space = strchr(buf, ' ');
- if (space) {
- match = MATCH_NONE;
- if (!decode_path(buf, buf, &len)) {
- if (!strcmp(buf, path))
- match = MATCH_EXACT;
- else if (!strncmp(buf, path, len)
- && (path[len] == '/' || !strcmp(buf, "/")))
- match = MATCH_PARENT;
- }
-
- found = pop(fd, buf, bufsize, space - buf + 1);
- if (found != 1)
- return found;
-
- switch (match) {
- case MATCH_EXACT:
- if (!strncmp(buf, "tmpfs", strlen("tmpfs")))
- *outcome = OUTCOME_TMPFS_MOUNT;
- else
- *outcome = OUTCOME_NON_TMPFS_MOUNT;
- break;
-
- case MATCH_PARENT:
- /* This mount obscures any previous ones. */
- *outcome = OUTCOME_NOTHING_MOUNTED;
- break;
- }
+ for (i = 0; tmpfs_dirs[i]; i++) {
+ dir = tmpfs_dirs[i];
+ if (check_tmpfs(dir) >= 0)
+ goto done;
}
- return next(fd, buf, bufsize, '\n');
+ dir = fallback_dir;
+warn:
+ printf("Warning: tempdir %s is not on tmpfs\n", dir);
+done:
+ /* Make a copy since getenv results may not remain valid forever. */
+ return strdup(dir);
}
-/* which_tmpdir is called only during early boot */
-static int checked_tmpdir = 0;
-
/*
- * Look for a tmpfs mounted at /dev/shm. I couldn't find a cleaner
- * way to do this than to parse /proc/mounts. statfs will return the
- * same filesystem magic number and fs id for both /dev and /dev/shm
- * when they are both tmpfs, so you can't tell if they are different
- * filesystems. Also, there seems to be no other way of finding the
- * mount point of a filesystem from within it.
- *
- * If a /dev/shm tmpfs entry is found, then we switch to using it.
- * Otherwise, we stay with the default /tmp.
+ * Create an unlinked tempfile in a suitable tempdir. template must be the
+ * basename part of the template with a leading '/'.
*/
-static void which_tmpdir(void)
+static int __init make_tempfile(const char *template)
{
+ char *tempname;
int fd;
- int found;
- int outcome;
- char *path;
- char *buf;
- size_t bufsize;
- if (checked_tmpdir)
- return;
-
- checked_tmpdir = 1;
-
- printf("Checking for tmpfs mount on /dev/shm...");
-
- path = realpath("/dev/shm", NULL);
- if (!path) {
- printf("failed to check real path, errno = %d\n", errno);
- return;
- }
- printf("%s...", path);
-
- /*
- * The buffer needs to be able to fit the full octal-escaped path, a
- * space, and a trailing null in order to successfully decode it.
- */
- bufsize = octal_encoded_length(path, " \t\n\\") + 2;
-
- if (bufsize < 128)
- bufsize = 128;
-
- buf = malloc(bufsize);
- if (!buf) {
- printf("malloc failed, errno = %d\n", errno);
- goto out;
- }
- buf[0] = '\0';
-
- fd = open("/proc/mounts", O_RDONLY);
- if (fd < 0) {
- printf("failed to open /proc/mounts, errno = %d\n", errno);
- goto out1;
- }
-
- outcome = OUTCOME_NOTHING_MOUNTED;
- while (1) {
- found = read_mount(fd, buf, bufsize, path, &outcome);
- if (found != 1)
- break;
- }
-
- if (found < 0) {
- printf("read returned errno %d\n", -found);
- } else {
- switch (outcome) {
- case OUTCOME_TMPFS_MOUNT:
- printf("OK\n");
- default_tmpdir = "/dev/shm";
- break;
-
- case OUTCOME_NON_TMPFS_MOUNT:
- printf("not tmpfs\n");
- break;
-
- default:
- printf("nothing mounted on /dev/shm\n");
- break;
+ if (tempdir == NULL) {
+ tempdir = choose_tempdir();
+ if (tempdir == NULL) {
+ fprintf(stderr, "Failed to choose tempdir: %s\n",
+ strerror(errno));
+ return -1;
}
}
- close(fd);
-out1:
- free(buf);
-out:
- free(path);
-}
-
-static int __init make_tempfile(const char *template, char **out_tempname,
- int do_unlink)
-{
- char *tempname;
- int fd;
-
- which_tmpdir();
- tempname = malloc(MAXPATHLEN);
+ tempname = malloc(strlen(tempdir) + strlen(template) + 1);
if (tempname == NULL)
return -1;
- find_tempdir();
- if ((tempdir == NULL) || (strlen(tempdir) >= MAXPATHLEN))
- goto out;
-
- if (template[0] != '/')
- strcpy(tempname, tempdir);
- else
- tempname[0] = '\0';
- strncat(tempname, template, MAXPATHLEN-1-strlen(tempname));
+ strcpy(tempname, tempdir);
+ strcat(tempname, template);
fd = mkstemp(tempname);
if (fd < 0) {
fprintf(stderr, "open - cannot create %s: %s\n", tempname,
strerror(errno));
goto out;
}
- if (do_unlink && (unlink(tempname) < 0)) {
+ if (unlink(tempname) < 0) {
perror("unlink");
goto close;
}
- if (out_tempname) {
- *out_tempname = tempname;
- } else
- free(tempname);
+ free(tempname);
return fd;
close:
close(fd);
@@ -351,14 +131,14 @@ out:
return -1;
}
-#define TEMPNAME_TEMPLATE "vm_file-XXXXXX"
+#define TEMPNAME_TEMPLATE "/vm_file-XXXXXX"
static int __init create_tmp_file(unsigned long long len)
{
int fd, err;
char zero;
- fd = make_tempfile(TEMPNAME_TEMPLATE, NULL, 1);
+ fd = make_tempfile(TEMPNAME_TEMPLATE);
if (fd < 0)
exit(1);
@@ -402,7 +182,6 @@ int __init create_mem_file(unsigned long long len)
return fd;
}
-
void __init check_tmpexec(void)
{
void *addr;
@@ -410,14 +189,13 @@ void __init check_tmpexec(void)
addr = mmap(NULL, UM_KERN_PAGE_SIZE,
PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
- printf("Checking PROT_EXEC mmap in %s...",tempdir);
- fflush(stdout);
+ printf("Checking PROT_EXEC mmap in %s...", tempdir);
if (addr == MAP_FAILED) {
err = errno;
- perror("failed");
+ printf("%s\n", strerror(err));
close(fd);
if (err == EPERM)
- printf("%s must be not mounted noexec\n",tempdir);
+ printf("%s must be not mounted noexec\n", tempdir);
exit(1);
}
printf("OK\n");
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 602f57e590b5..33f71b01fd22 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -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)
@@ -250,8 +253,8 @@ archclean:
PHONY += kvmconfig
kvmconfig:
$(if $(wildcard $(objtree)/.config),, $(error You need an existing .config for this target))
- $(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh -m -O $(objtree) $(objtree)/.config arch/x86/configs/kvm_guest.config
- $(Q)yes "" | $(MAKE) oldconfig
+ $(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh -m -O $(objtree) $(objtree)/.config $(srctree)/arch/x86/configs/kvm_guest.config
+ $(Q)yes "" | $(MAKE) -f $(srctree)/Makefile oldconfig
define archhelp
echo '* bzImage - Compressed kernel image (arch/x86/boot/bzImage)'
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index abb9eba61b50..dbe8dd2fe247 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -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) > $@
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index 17684615374b..57ab74df7eea 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -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,
diff --git a/arch/x86/include/asm/hpet.h b/arch/x86/include/asm/hpet.h
index b18df579c0e9..36f7125945e3 100644
--- a/arch/x86/include/asm/hpet.h
+++ b/arch/x86/include/asm/hpet.h
@@ -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;
diff --git a/arch/x86/include/asm/hugetlb.h b/arch/x86/include/asm/hugetlb.h
index a8091216963b..68c05398bba9 100644
--- a/arch/x86/include/asm/hugetlb.h
+++ b/arch/x86/include/asm/hugetlb.h
@@ -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)
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index fcaf9c961265..7de069afb382 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -60,7 +60,7 @@
| X86_CR4_PSE | X86_CR4_PAE | X86_CR4_MCE \
| X86_CR4_PGE | X86_CR4_PCE | X86_CR4_OSFXSR | X86_CR4_PCIDE \
| X86_CR4_OSXSAVE | X86_CR4_SMEP | X86_CR4_FSGSBASE \
- | X86_CR4_OSXMMEXCPT | X86_CR4_VMXE))
+ | X86_CR4_OSXMMEXCPT | X86_CR4_VMXE | X86_CR4_SMAP))
#define CR8_RESERVED_BITS (~(unsigned long)X86_CR8_TPR)
diff --git a/arch/x86/include/asm/page_64_types.h b/arch/x86/include/asm/page_64_types.h
index 8de6d9cf3b95..678205195ae1 100644
--- a/arch/x86/include/asm/page_64_types.h
+++ b/arch/x86/include/asm/page_64_types.h
@@ -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))
diff --git a/arch/x86/include/asm/xen/hypercall.h b/arch/x86/include/asm/xen/hypercall.h
index e709884d0ef9..ca08a27b90b3 100644
--- a/arch/x86/include/asm/xen/hypercall.h
+++ b/arch/x86/include/asm/xen/hypercall.h
@@ -343,7 +343,7 @@ HYPERVISOR_memory_op(unsigned int cmd, void *arg)
}
static inline int
-HYPERVISOR_multicall(void *call_list, int nr_calls)
+HYPERVISOR_multicall(void *call_list, uint32_t nr_calls)
{
return _hypercall2(int, multicall, call_list, nr_calls);
}
diff --git a/arch/x86/include/asm/xen/interface.h b/arch/x86/include/asm/xen/interface.h
index fd9cb7695b5f..3400dbaec3c3 100644
--- a/arch/x86/include/asm/xen/interface.h
+++ b/arch/x86/include/asm/xen/interface.h
@@ -54,6 +54,9 @@ typedef unsigned long xen_pfn_t;
#define PRI_xen_pfn "lx"
typedef unsigned long xen_ulong_t;
#define PRI_xen_ulong "lx"
+typedef long xen_long_t;
+#define PRI_xen_long "lx"
+
/* Guest handles for primitive C types. */
__DEFINE_GUEST_HANDLE(uchar, unsigned char);
__DEFINE_GUEST_HANDLE(uint, unsigned int);
diff --git a/arch/x86/include/uapi/asm/msr-index.h b/arch/x86/include/uapi/asm/msr-index.h
index c827ace3121b..fcf2b3ae1bf0 100644
--- a/arch/x86/include/uapi/asm/msr-index.h
+++ b/arch/x86/include/uapi/asm/msr-index.h
@@ -384,7 +384,7 @@
#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
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c
index 3a2ae4c88948..31368207837c 100644
--- a/arch/x86/kernel/acpi/sleep.c
+++ b/arch/x86/kernel/acpi/sleep.c
@@ -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);
}
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 6ad4658de705..992060e09897 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -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;
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index eeee23ff75ef..68317c80de7f 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -598,7 +598,6 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
{
struct mce m;
int i;
- unsigned long *v;
this_cpu_inc(mce_poll_count);
@@ -618,8 +617,7 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
if (!(m.status & MCI_STATUS_VAL))
continue;
- v = &get_cpu_var(mce_polled_error);
- set_bit(0, v);
+ this_cpu_write(mce_polled_error, 1);
/*
* Uncorrected or signalled events are handled by the exception
* handler when it is enabled, so don't process those here.
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel.c b/arch/x86/kernel/cpu/mcheck/mce_intel.c
index 3bdb95ae8c43..9a316b21df8b 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_intel.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_intel.c
@@ -42,7 +42,7 @@ static DEFINE_PER_CPU(mce_banks_t, mce_banks_owned);
* cmci_discover_lock protects against parallel discovery attempts
* which could race against each other.
*/
-static DEFINE_RAW_SPINLOCK(cmci_discover_lock);
+static DEFINE_SPINLOCK(cmci_discover_lock);
#define CMCI_THRESHOLD 1
#define CMCI_POLL_INTERVAL (30 * HZ)
@@ -144,14 +144,14 @@ static void cmci_storm_disable_banks(void)
int bank;
u64 val;
- raw_spin_lock_irqsave(&cmci_discover_lock, flags);
+ spin_lock_irqsave(&cmci_discover_lock, flags);
owned = __get_cpu_var(mce_banks_owned);
for_each_set_bit(bank, owned, MAX_NR_BANKS) {
rdmsrl(MSR_IA32_MCx_CTL2(bank), val);
val &= ~MCI_CTL2_CMCI_EN;
wrmsrl(MSR_IA32_MCx_CTL2(bank), val);
}
- raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
+ spin_unlock_irqrestore(&cmci_discover_lock, flags);
}
static bool cmci_storm_detect(void)
@@ -211,7 +211,7 @@ static void cmci_discover(int banks)
int i;
int bios_wrong_thresh = 0;
- raw_spin_lock_irqsave(&cmci_discover_lock, flags);
+ spin_lock_irqsave(&cmci_discover_lock, flags);
for (i = 0; i < banks; i++) {
u64 val;
int bios_zero_thresh = 0;
@@ -266,7 +266,7 @@ static void cmci_discover(int banks)
WARN_ON(!test_bit(i, __get_cpu_var(mce_poll_banks)));
}
}
- raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
+ spin_unlock_irqrestore(&cmci_discover_lock, flags);
if (mca_cfg.bios_cmci_threshold && bios_wrong_thresh) {
pr_info_once(
"bios_cmci_threshold: Some banks do not have valid thresholds set\n");
@@ -316,10 +316,10 @@ void cmci_clear(void)
if (!cmci_supported(&banks))
return;
- raw_spin_lock_irqsave(&cmci_discover_lock, flags);
+ spin_lock_irqsave(&cmci_discover_lock, flags);
for (i = 0; i < banks; i++)
__cmci_disable_bank(i);
- raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
+ spin_unlock_irqrestore(&cmci_discover_lock, flags);
}
static void cmci_rediscover_work_func(void *arg)
@@ -360,9 +360,9 @@ void cmci_disable_bank(int bank)
if (!cmci_supported(&banks))
return;
- raw_spin_lock_irqsave(&cmci_discover_lock, flags);
+ spin_lock_irqsave(&cmci_discover_lock, flags);
__cmci_disable_bank(bank);
- raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
+ spin_unlock_irqrestore(&cmci_discover_lock, flags);
}
static void intel_init_cmci(void)
diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c
index d921b7ee6595..36a1bb6d1ee0 100644
--- a/arch/x86/kernel/cpu/mcheck/therm_throt.c
+++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c
@@ -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);
diff --git a/arch/x86/kernel/cpu/mcheck/threshold.c b/arch/x86/kernel/cpu/mcheck/threshold.c
index fe6b1c86645b..7245980186ee 100644
--- a/arch/x86/kernel/cpu/mcheck/threshold.c
+++ b/arch/x86/kernel/cpu/mcheck/threshold.c
@@ -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);
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index aa333d966886..adb02aa62af5 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -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
};
diff --git a/arch/x86/kernel/cpu/perf_event_intel_rapl.c b/arch/x86/kernel/cpu/perf_event_intel_rapl.c
index 059218ed5208..619f7699487a 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_rapl.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_rapl.c
@@ -59,7 +59,7 @@
#define INTEL_RAPL_PKG 0x2 /* pseudo-encoding */
#define RAPL_IDX_RAM_NRG_STAT 2 /* DRAM */
#define INTEL_RAPL_RAM 0x3 /* pseudo-encoding */
-#define RAPL_IDX_PP1_NRG_STAT 3 /* DRAM */
+#define RAPL_IDX_PP1_NRG_STAT 3 /* gpu */
#define INTEL_RAPL_PP1 0x4 /* pseudo-encoding */
/* Clients have PP0, PKG */
@@ -72,6 +72,12 @@
1<<RAPL_IDX_PKG_NRG_STAT|\
1<<RAPL_IDX_RAM_NRG_STAT)
+/* Servers have PP0, PKG, RAM, PP1 */
+#define RAPL_IDX_HSW (1<<RAPL_IDX_PP0_NRG_STAT|\
+ 1<<RAPL_IDX_PKG_NRG_STAT|\
+ 1<<RAPL_IDX_RAM_NRG_STAT|\
+ 1<<RAPL_IDX_PP1_NRG_STAT)
+
/*
* event code: LSB 8 bits, passed in attr->config
* any other bit is reserved
@@ -425,6 +431,24 @@ static struct attribute *rapl_events_cln_attr[] = {
NULL,
};
+static struct attribute *rapl_events_hsw_attr[] = {
+ EVENT_PTR(rapl_cores),
+ EVENT_PTR(rapl_pkg),
+ EVENT_PTR(rapl_gpu),
+ EVENT_PTR(rapl_ram),
+
+ EVENT_PTR(rapl_cores_unit),
+ EVENT_PTR(rapl_pkg_unit),
+ EVENT_PTR(rapl_gpu_unit),
+ EVENT_PTR(rapl_ram_unit),
+
+ EVENT_PTR(rapl_cores_scale),
+ EVENT_PTR(rapl_pkg_scale),
+ EVENT_PTR(rapl_gpu_scale),
+ EVENT_PTR(rapl_ram_scale),
+ NULL,
+};
+
static struct attribute_group rapl_pmu_events_group = {
.name = "events",
.attrs = NULL, /* patched at runtime */
@@ -511,6 +535,7 @@ static int rapl_cpu_prepare(int cpu)
struct rapl_pmu *pmu = per_cpu(rapl_pmu, cpu);
int phys_id = topology_physical_package_id(cpu);
u64 ms;
+ u64 msr_rapl_power_unit_bits;
if (pmu)
return 0;
@@ -518,6 +543,10 @@ static int rapl_cpu_prepare(int cpu)
if (phys_id < 0)
return -1;
+ /* 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));
if (!pmu)
return -1;
@@ -531,8 +560,7 @@ static int rapl_cpu_prepare(int cpu)
*
* we cache in local PMU instance
*/
- rdmsrl(MSR_RAPL_POWER_UNIT, pmu->hw_unit);
- pmu->hw_unit = (pmu->hw_unit >> 8) & 0x1FULL;
+ pmu->hw_unit = (msr_rapl_power_unit_bits >> 8) & 0x1FULL;
pmu->pmu = &rapl_pmu_class;
/*
@@ -631,11 +659,14 @@ static int __init rapl_pmu_init(void)
switch (boot_cpu_data.x86_model) {
case 42: /* Sandy Bridge */
case 58: /* Ivy Bridge */
- case 60: /* Haswell */
- case 69: /* Haswell-Celeron */
rapl_cntr_mask = RAPL_IDX_CLN;
rapl_pmu_events_group.attrs = rapl_events_cln_attr;
break;
+ case 60: /* Haswell */
+ case 69: /* Haswell-Celeron */
+ rapl_cntr_mask = RAPL_IDX_HSW;
+ rapl_pmu_events_group.attrs = rapl_events_hsw_attr;
+ break;
case 45: /* Sandy Bridge-EP */
case 62: /* IvyTown */
rapl_cntr_mask = RAPL_IDX_SRV;
@@ -650,7 +681,9 @@ static int __init rapl_pmu_init(void)
cpu_notifier_register_begin();
for_each_online_cpu(cpu) {
- rapl_cpu_prepare(cpu);
+ ret = rapl_cpu_prepare(cpu);
+ if (ret)
+ goto out;
rapl_cpu_init(cpu);
}
@@ -673,6 +706,7 @@ static int __init rapl_pmu_init(void)
hweight32(rapl_cntr_mask),
ktime_to_ms(pmu->timer_interval));
+out:
cpu_notifier_register_done();
return 0;
diff --git a/arch/x86/kernel/cpu/rdrand.c b/arch/x86/kernel/cpu/rdrand.c
index 384df5105fbc..136ac74dee82 100644
--- a/arch/x86/kernel/cpu/rdrand.c
+++ b/arch/x86/kernel/cpu/rdrand.c
@@ -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);
diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c
index b0cc3809723d..6cda0baeac9d 100644
--- a/arch/x86/kernel/early-quirks.c
+++ b/arch/x86/kernel/early-quirks.c
@@ -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>
@@ -240,7 +241,7 @@ static u32 __init intel_stolen_base(int num, int slot, int func, size_t stolen_s
return base;
}
-#define KB(x) ((x) * 1024)
+#define KB(x) ((x) * 1024UL)
#define MB(x) (KB (KB (x)))
#define GB(x) (MB (KB (x)))
@@ -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},
{}
};
diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c
index c61a14a4a310..d6c1b9836995 100644
--- a/arch/x86/kernel/head32.c
+++ b/arch/x86/kernel/head32.c
@@ -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);
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 85126ccbdf6b..068054f4bf20 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -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;
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 8d80ae011603..4177bfbc80b0 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -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;
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index 79a3f9682871..61b17dc2c277 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -897,9 +897,10 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
struct kprobe *cur = kprobe_running();
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
- switch (kcb->kprobe_status) {
- case KPROBE_HIT_SS:
- case KPROBE_REENTER:
+ if (unlikely(regs->ip == (unsigned long)cur->ainsn.insn)) {
+ /* This must happen on single-stepping */
+ WARN_ON(kcb->kprobe_status != KPROBE_HIT_SS &&
+ kcb->kprobe_status != KPROBE_REENTER);
/*
* We are here because the instruction being single
* stepped caused a page fault. We reset the current
@@ -914,9 +915,8 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
else
reset_current_kprobe();
preempt_enable_no_resched();
- break;
- case KPROBE_HIT_ACTIVE:
- case KPROBE_HIT_SSDONE:
+ } else if (kcb->kprobe_status == KPROBE_HIT_ACTIVE ||
+ kcb->kprobe_status == KPROBE_HIT_SSDONE) {
/*
* We increment the nmissed count for accounting,
* we can also use npre/npostfault count for accounting
@@ -945,10 +945,8 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
* fixup routine could not handle it,
* Let do_page_fault() fix it.
*/
- break;
- default:
- break;
}
+
return 0;
}
diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c
index af1d14a9ebda..dcbbaa165bde 100644
--- a/arch/x86/kernel/ldt.c
+++ b/arch/x86/kernel/ldt.c
@@ -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;
}
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 9c0280f93d05..898d077617a9 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -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)
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 654b46574b91..52b1157c53eb 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -114,8 +114,8 @@ EXPORT_SYMBOL(machine_real_restart);
*/
static int __init set_pci_reboot(const struct dmi_system_id *d)
{
- if (reboot_type != BOOT_CF9) {
- reboot_type = BOOT_CF9;
+ if (reboot_type != BOOT_CF9_FORCE) {
+ reboot_type = BOOT_CF9_FORCE;
pr_info("%s series board detected. Selecting %s-method for reboots.\n",
d->ident, "PCI");
}
@@ -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,
@@ -458,20 +468,23 @@ void __attribute__((weak)) mach_reboot_fixups(void)
}
/*
- * Windows compatible x86 hardware expects the following on reboot:
+ * To the best of our knowledge Windows compatible x86 hardware expects
+ * the following on reboot:
*
* 1) If the FADT has the ACPI reboot register flag set, try it
* 2) If still alive, write to the keyboard controller
* 3) If still alive, write to the ACPI reboot register again
* 4) If still alive, write to the keyboard controller again
* 5) If still alive, call the EFI runtime service to reboot
- * 6) If still alive, write to the PCI IO port 0xCF9 to reboot
- * 7) If still alive, inform BIOS to do a proper reboot
+ * 6) If no EFI runtime service, call the BIOS to do a reboot
+ *
+ * We default to following the same pattern. We also have
+ * two other reboot methods: 'triple fault' and 'PCI', which
+ * can be triggered via the reboot= kernel boot option or
+ * via quirks.
*
- * If the machine is still alive at this stage, it gives up. We default to
- * following the same pattern, except that if we're still alive after (7) we'll
- * try to force a triple fault and then cycle between hitting the keyboard
- * controller and doing that
+ * This means that this function can never return, it can misbehave
+ * by not rebooting properly and hanging.
*/
static void native_machine_emergency_restart(void)
{
@@ -492,6 +505,11 @@ static void native_machine_emergency_restart(void)
for (;;) {
/* Could also try the reset bit in the Hammer NB */
switch (reboot_type) {
+ case BOOT_ACPI:
+ acpi_reboot();
+ reboot_type = BOOT_KBD;
+ break;
+
case BOOT_KBD:
mach_reboot_fixups(); /* For board specific fixups */
@@ -509,43 +527,29 @@ static void native_machine_emergency_restart(void)
}
break;
- case BOOT_TRIPLE:
- load_idt(&no_idt);
- __asm__ __volatile__("int3");
-
- /* We're probably dead after this, but... */
- reboot_type = BOOT_KBD;
- break;
-
- case BOOT_BIOS:
- machine_real_restart(MRR_BIOS);
-
- /* We're probably dead after this, but... */
- reboot_type = BOOT_TRIPLE;
- break;
-
- case BOOT_ACPI:
- acpi_reboot();
- reboot_type = BOOT_KBD;
- break;
-
case BOOT_EFI:
if (efi_enabled(EFI_RUNTIME_SERVICES))
efi.reset_system(reboot_mode == REBOOT_WARM ?
EFI_RESET_WARM :
EFI_RESET_COLD,
EFI_SUCCESS, 0, NULL);
- reboot_type = BOOT_CF9_COND;
+ reboot_type = BOOT_BIOS;
+ break;
+
+ case BOOT_BIOS:
+ machine_real_restart(MRR_BIOS);
+
+ /* We're probably dead after this, but... */
+ reboot_type = BOOT_CF9_SAFE;
break;
- case BOOT_CF9:
+ case BOOT_CF9_FORCE:
port_cf9_safe = true;
/* Fall through */
- case BOOT_CF9_COND:
+ case BOOT_CF9_SAFE:
if (port_cf9_safe) {
- u8 reboot_code = reboot_mode == REBOOT_WARM ?
- 0x06 : 0x0E;
+ u8 reboot_code = reboot_mode == REBOOT_WARM ? 0x06 : 0x0E;
u8 cf9 = inb(0xcf9) & ~reboot_code;
outb(cf9|2, 0xcf9); /* Request hard reset */
udelay(50);
@@ -553,7 +557,15 @@ static void native_machine_emergency_restart(void)
outb(cf9|reboot_code, 0xcf9);
udelay(50);
}
- reboot_type = BOOT_BIOS;
+ reboot_type = BOOT_TRIPLE;
+ break;
+
+ case BOOT_TRIPLE:
+ load_idt(&no_idt);
+ __asm__ __volatile__("int3");
+
+ /* We're probably dead after this, but... */
+ reboot_type = BOOT_KBD;
break;
}
}
diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c
index 7c3a5a61f2e4..be8e1bde07aa 100644
--- a/arch/x86/kernel/smp.c
+++ b/arch/x86/kernel/smp.c
@@ -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();
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 57409f6b8c62..f73b5d435bdc 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -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)
{
}
diff --git a/arch/x86/kernel/vsmp_64.c b/arch/x86/kernel/vsmp_64.c
index f6584a90aba3..b99b9ad8540c 100644
--- a/arch/x86/kernel/vsmp_64.c
+++ b/arch/x86/kernel/vsmp_64.c
@@ -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)
diff --git a/arch/x86/kernel/vsyscall_gtod.c b/arch/x86/kernel/vsyscall_gtod.c
index f9c6e56e14b5..9531fbb123ba 100644
--- a/arch/x86/kernel/vsyscall_gtod.c
+++ b/arch/x86/kernel/vsyscall_gtod.c
@@ -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)) {
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index bea60671ef8a..f47a104a749c 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -308,7 +308,7 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
const u32 kvm_supported_word9_x86_features =
F(FSGSBASE) | F(BMI1) | F(HLE) | F(AVX2) | F(SMEP) |
F(BMI2) | F(ERMS) | f_invpcid | F(RTM) | f_mpx | F(RDSEED) |
- F(ADX);
+ F(ADX) | F(SMAP);
/* all calls to cpuid_count() should be made on the same cpu */
get_cpu();
diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h
index a2a1bb7ed8c1..eeecbed26ac7 100644
--- a/arch/x86/kvm/cpuid.h
+++ b/arch/x86/kvm/cpuid.h
@@ -48,6 +48,14 @@ static inline bool guest_cpuid_has_smep(struct kvm_vcpu *vcpu)
return best && (best->ebx & bit(X86_FEATURE_SMEP));
}
+static inline bool guest_cpuid_has_smap(struct kvm_vcpu *vcpu)
+{
+ struct kvm_cpuid_entry2 *best;
+
+ best = kvm_find_cpuid_entry(vcpu, 7, 0);
+ return best && (best->ebx & bit(X86_FEATURE_SMAP));
+}
+
static inline bool guest_cpuid_has_fsgsbase(struct kvm_vcpu *vcpu)
{
struct kvm_cpuid_entry2 *best;
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index f5704d9e5ddc..813d31038b93 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -3601,20 +3601,27 @@ static void reset_rsvds_bits_mask_ept(struct kvm_vcpu *vcpu,
}
}
-static void update_permission_bitmask(struct kvm_vcpu *vcpu,
+void update_permission_bitmask(struct kvm_vcpu *vcpu,
struct kvm_mmu *mmu, bool ept)
{
unsigned bit, byte, pfec;
u8 map;
- bool fault, x, w, u, wf, uf, ff, smep;
+ bool fault, x, w, u, wf, uf, ff, smapf, cr4_smap, cr4_smep, smap = 0;
- smep = kvm_read_cr4_bits(vcpu, X86_CR4_SMEP);
+ cr4_smep = kvm_read_cr4_bits(vcpu, X86_CR4_SMEP);
+ cr4_smap = kvm_read_cr4_bits(vcpu, X86_CR4_SMAP);
for (byte = 0; byte < ARRAY_SIZE(mmu->permissions); ++byte) {
pfec = byte << 1;
map = 0;
wf = pfec & PFERR_WRITE_MASK;
uf = pfec & PFERR_USER_MASK;
ff = pfec & PFERR_FETCH_MASK;
+ /*
+ * PFERR_RSVD_MASK bit is set in PFEC if the access is not
+ * subject to SMAP restrictions, and cleared otherwise. The
+ * bit is only meaningful if the SMAP bit is set in CR4.
+ */
+ smapf = !(pfec & PFERR_RSVD_MASK);
for (bit = 0; bit < 8; ++bit) {
x = bit & ACC_EXEC_MASK;
w = bit & ACC_WRITE_MASK;
@@ -3626,12 +3633,33 @@ static void update_permission_bitmask(struct kvm_vcpu *vcpu,
/* Allow supervisor writes if !cr0.wp */
w |= !is_write_protection(vcpu) && !uf;
/* Disallow supervisor fetches of user code if cr4.smep */
- x &= !(smep && u && !uf);
+ x &= !(cr4_smep && u && !uf);
+
+ /*
+ * SMAP:kernel-mode data accesses from user-mode
+ * mappings should fault. A fault is considered
+ * as a SMAP violation if all of the following
+ * conditions are ture:
+ * - X86_CR4_SMAP is set in CR4
+ * - An user page is accessed
+ * - Page fault in kernel mode
+ * - if CPL = 3 or X86_EFLAGS_AC is clear
+ *
+ * Here, we cover the first three conditions.
+ * The fourth is computed dynamically in
+ * permission_fault() and is in smapf.
+ *
+ * Also, SMAP does not affect instruction
+ * fetches, add the !ff check here to make it
+ * clearer.
+ */
+ smap = cr4_smap && u && !uf && !ff;
} else
/* Not really needed: no U/S accesses on ept */
u = 1;
- fault = (ff && !x) || (uf && !u) || (wf && !w);
+ fault = (ff && !x) || (uf && !u) || (wf && !w) ||
+ (smapf && smap);
map |= fault << bit;
}
mmu->permissions[byte] = map;
diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h
index 292615274358..3842e70bdb7c 100644
--- a/arch/x86/kvm/mmu.h
+++ b/arch/x86/kvm/mmu.h
@@ -44,11 +44,17 @@
#define PT_DIRECTORY_LEVEL 2
#define PT_PAGE_TABLE_LEVEL 1
-#define PFERR_PRESENT_MASK (1U << 0)
-#define PFERR_WRITE_MASK (1U << 1)
-#define PFERR_USER_MASK (1U << 2)
-#define PFERR_RSVD_MASK (1U << 3)
-#define PFERR_FETCH_MASK (1U << 4)
+#define PFERR_PRESENT_BIT 0
+#define PFERR_WRITE_BIT 1
+#define PFERR_USER_BIT 2
+#define PFERR_RSVD_BIT 3
+#define PFERR_FETCH_BIT 4
+
+#define PFERR_PRESENT_MASK (1U << PFERR_PRESENT_BIT)
+#define PFERR_WRITE_MASK (1U << PFERR_WRITE_BIT)
+#define PFERR_USER_MASK (1U << PFERR_USER_BIT)
+#define PFERR_RSVD_MASK (1U << PFERR_RSVD_BIT)
+#define PFERR_FETCH_MASK (1U << PFERR_FETCH_BIT)
int kvm_mmu_get_spte_hierarchy(struct kvm_vcpu *vcpu, u64 addr, u64 sptes[4]);
void kvm_mmu_set_mmio_spte_mask(u64 mmio_mask);
@@ -73,6 +79,8 @@ int handle_mmio_page_fault_common(struct kvm_vcpu *vcpu, u64 addr, bool direct);
void kvm_init_shadow_mmu(struct kvm_vcpu *vcpu, struct kvm_mmu *context);
void kvm_init_shadow_ept_mmu(struct kvm_vcpu *vcpu, struct kvm_mmu *context,
bool execonly);
+void update_permission_bitmask(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
+ bool ept);
static inline unsigned int kvm_mmu_available_pages(struct kvm *kvm)
{
@@ -110,10 +118,30 @@ static inline bool is_write_protection(struct kvm_vcpu *vcpu)
* Will a fault with a given page-fault error code (pfec) cause a permission
* fault with the given access (in ACC_* format)?
*/
-static inline bool permission_fault(struct kvm_mmu *mmu, unsigned pte_access,
- unsigned pfec)
+static inline bool permission_fault(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
+ unsigned pte_access, unsigned pfec)
{
- return (mmu->permissions[pfec >> 1] >> pte_access) & 1;
+ int cpl = kvm_x86_ops->get_cpl(vcpu);
+ unsigned long rflags = kvm_x86_ops->get_rflags(vcpu);
+
+ /*
+ * If CPL < 3, SMAP prevention are disabled if EFLAGS.AC = 1.
+ *
+ * If CPL = 3, SMAP applies to all supervisor-mode data accesses
+ * (these are implicit supervisor accesses) regardless of the value
+ * of EFLAGS.AC.
+ *
+ * This computes (cpl < 3) && (rflags & X86_EFLAGS_AC), leaving
+ * the result in X86_EFLAGS_AC. We then insert it in place of
+ * the PFERR_RSVD_MASK bit; this bit will always be zero in pfec,
+ * but it will be one in index if SMAP checks are being overridden.
+ * It is important to keep this branchless.
+ */
+ unsigned long smap = (cpl - 3) & (rflags & X86_EFLAGS_AC);
+ int index = (pfec >> 1) +
+ (smap >> (X86_EFLAGS_AC_BIT - PFERR_RSVD_BIT + 1));
+
+ return (mmu->permissions[index] >> pte_access) & 1;
}
void kvm_mmu_invalidate_zap_all_pages(struct kvm *kvm);
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index b1e6c1bf68d3..123efd3ec29f 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -353,7 +353,7 @@ retry_walk:
walker->ptes[walker->level - 1] = pte;
} while (!is_last_gpte(mmu, walker->level, pte));
- if (unlikely(permission_fault(mmu, pte_access, access))) {
+ if (unlikely(permission_fault(vcpu, mmu, pte_access, access))) {
errcode |= PFERR_PRESENT_MASK;
goto error;
}
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 1320e0f8e611..138ceffc6377 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -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()) {
@@ -3484,13 +3521,14 @@ static int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
hw_cr4 &= ~X86_CR4_PAE;
hw_cr4 |= X86_CR4_PSE;
/*
- * SMEP is disabled if CPU is in non-paging mode in
- * hardware. However KVM always uses paging mode to
+ * SMEP/SMAP is disabled if CPU is in non-paging mode
+ * in hardware. However KVM always uses paging mode to
* emulate guest non-paging mode with TDP.
- * To emulate this behavior, SMEP needs to be manually
- * disabled when guest switches to non-paging mode.
+ * To emulate this behavior, SMEP/SMAP needs to be
+ * manually disabled when guest switches to non-paging
+ * mode.
*/
- hw_cr4 &= ~X86_CR4_SMEP;
+ hw_cr4 &= ~(X86_CR4_SMEP | X86_CR4_SMAP);
} else if (!(cr4 & X86_CR4_PAE)) {
hw_cr4 &= ~X86_CR4_PAE;
}
@@ -7740,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;
@@ -7777,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;
@@ -8802,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
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 9d1b5cd4d34c..20316c67b824 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -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();
@@ -652,6 +654,9 @@ int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
if (!guest_cpuid_has_smep(vcpu) && (cr4 & X86_CR4_SMEP))
return 1;
+ if (!guest_cpuid_has_smap(vcpu) && (cr4 & X86_CR4_SMAP))
+ return 1;
+
if (!guest_cpuid_has_fsgsbase(vcpu) && (cr4 & X86_CR4_FSGSBASE))
return 1;
@@ -680,6 +685,9 @@ int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
(!(cr4 & X86_CR4_PCIDE) && (old_cr4 & X86_CR4_PCIDE)))
kvm_mmu_reset_context(vcpu);
+ if ((cr4 ^ old_cr4) & X86_CR4_SMAP)
+ update_permission_bitmask(vcpu, vcpu->arch.walk_mmu, false);
+
if ((cr4 ^ old_cr4) & X86_CR4_OSXSAVE)
kvm_update_cpuid(vcpu);
@@ -1117,7 +1125,6 @@ static inline u64 get_kernel_ns(void)
{
struct timespec ts;
- WARN_ON(preemptible());
ktime_get_ts(&ts);
monotonic_to_bootbased(&ts);
return timespec_to_ns(&ts);
@@ -1481,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);
@@ -4164,7 +4172,8 @@ static int vcpu_mmio_gva_to_gpa(struct kvm_vcpu *vcpu, unsigned long gva,
| (write ? PFERR_WRITE_MASK : 0);
if (vcpu_match_mmio_gva(vcpu, gva)
- && !permission_fault(vcpu->arch.walk_mmu, vcpu->arch.access, access)) {
+ && !permission_fault(vcpu, vcpu->arch.walk_mmu,
+ vcpu->arch.access, access)) {
*gpa = vcpu->arch.mmio_gfn << PAGE_SHIFT |
(gva & (PAGE_SIZE - 1));
trace_vcpu_match_mmio(gva, *gpa, write, false);
@@ -6939,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;
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index ad1fb5f53925..aae94132bc24 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -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;
}
diff --git a/arch/x86/lib/msr.c b/arch/x86/lib/msr.c
index db9db446b71a..43623739c7cf 100644
--- a/arch/x86/lib/msr.c
+++ b/arch/x86/lib/msr.c
@@ -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;
diff --git a/arch/x86/math-emu/errors.c b/arch/x86/math-emu/errors.c
index a5449089cd9f..9e6545f269e5 100644
--- a/arch/x86/math-emu/errors.c
+++ b/arch/x86/math-emu/errors.c
@@ -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;
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index dc017735bb91..6d5663a599a7 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -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];
diff --git a/arch/x86/platform/efi/early_printk.c b/arch/x86/platform/efi/early_printk.c
index 81b506d5befd..524142117296 100644
--- a/arch/x86/platform/efi/early_printk.c
+++ b/arch/x86/platform/efi/early_printk.c
@@ -14,48 +14,92 @@
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;
}
diff --git a/arch/x86/platform/olpc/olpc-xo1-pm.c b/arch/x86/platform/olpc/olpc-xo1-pm.c
index ff0174dda810..a9acde72d4ed 100644
--- a/arch/x86/platform/olpc/olpc-xo1-pm.c
+++ b/arch/x86/platform/olpc/olpc-xo1-pm.c
@@ -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());
diff --git a/arch/x86/power/hibernate_64.c b/arch/x86/power/hibernate_64.c
index 304fca20d96e..35e2bb6c0f37 100644
--- a/arch/x86/power/hibernate_64.c
+++ b/arch/x86/power/hibernate_64.c
@@ -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
diff --git a/arch/x86/syscalls/Makefile b/arch/x86/syscalls/Makefile
index f325af26107c..3323c2745248 100644
--- a/arch/x86/syscalls/Makefile
+++ b/arch/x86/syscalls/Makefile
@@ -54,5 +54,7 @@ syshdr-$(CONFIG_X86_64) += syscalls_64.h
targets += $(uapisyshdr-y) $(syshdr-y)
+PHONY += all
all: $(addprefix $(uapi)/,$(uapisyshdr-y))
all: $(addprefix $(out)/,$(syshdr-y))
+ @:
diff --git a/arch/x86/syscalls/syscall_32.tbl b/arch/x86/syscalls/syscall_32.tbl
index 96bc506ac6de..d6b867921612 100644
--- a/arch/x86/syscalls/syscall_32.tbl
+++ b/arch/x86/syscalls/syscall_32.tbl
@@ -359,3 +359,4 @@
350 i386 finit_module sys_finit_module
351 i386 sched_setattr sys_sched_setattr
352 i386 sched_getattr sys_sched_getattr
+353 i386 renameat2 sys_renameat2
diff --git a/arch/x86/tools/Makefile b/arch/x86/tools/Makefile
index e8120346903b..604a37efd4d5 100644
--- a/arch/x86/tools/Makefile
+++ b/arch/x86/tools/Makefile
@@ -40,4 +40,6 @@ $(obj)/insn_sanity.o: $(srctree)/arch/x86/lib/insn.c $(srctree)/arch/x86/lib/ina
HOST_EXTRACFLAGS += -I$(srctree)/tools/include
hostprogs-y += relocs
relocs-objs := relocs_32.o relocs_64.o relocs_common.o
+PHONY += relocs
relocs: $(obj)/relocs
+ @:
diff --git a/arch/x86/vdso/vdso-layout.lds.S b/arch/x86/vdso/vdso-layout.lds.S
index 2e263f367b13..9df017ab2285 100644
--- a/arch/x86/vdso/vdso-layout.lds.S
+++ b/arch/x86/vdso/vdso-layout.lds.S
@@ -9,12 +9,9 @@ SECTIONS
#ifdef BUILD_VDSO32
#include <asm/vdso32.h>
- .hpet_sect : {
- hpet_page = . - VDSO_OFFSET(VDSO_HPET_PAGE);
- } :text :hpet_sect
+ hpet_page = . - VDSO_OFFSET(VDSO_HPET_PAGE);
- .vvar_sect : {
- vvar = . - VDSO_OFFSET(VDSO_VVAR_PAGE);
+ vvar = . - VDSO_OFFSET(VDSO_VVAR_PAGE);
/* Place all vvars at the offsets in asm/vvar.h. */
#define EMIT_VVAR(name, offset) vvar_ ## name = vvar + offset;
@@ -22,7 +19,6 @@ SECTIONS
#include <asm/vvar.h>
#undef __VVAR_KERNEL_LDS
#undef EMIT_VVAR
- } :text :vvar_sect
#endif
. = SIZEOF_HEADERS;
@@ -61,7 +57,12 @@ SECTIONS
*/
. = ALIGN(0x100);
- .text : { *(.text*) } :text =0x90909090
+ .text : { *(.text*) } :text =0x90909090,
+
+ /*
+ * The comma above works around a bug in gold:
+ * https://sourceware.org/bugzilla/show_bug.cgi?id=16804
+ */
/DISCARD/ : {
*(.discard)
@@ -84,8 +85,4 @@ PHDRS
dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
note PT_NOTE FLAGS(4); /* PF_R */
eh_frame_hdr PT_GNU_EH_FRAME;
-#ifdef BUILD_VDSO32
- vvar_sect PT_NULL FLAGS(4); /* PF_R */
- hpet_sect PT_NULL FLAGS(4); /* PF_R */
-#endif
}
diff --git a/arch/x86/vdso/vdso32-setup.c b/arch/x86/vdso/vdso32-setup.c
index 00348980a3a6..e1f220e3ca68 100644
--- a/arch/x86/vdso/vdso32-setup.c
+++ b/arch/x86/vdso/vdso32-setup.c
@@ -39,6 +39,7 @@
#ifdef CONFIG_X86_64
#define vdso_enabled sysctl_vsyscall32
#define arch_setup_additional_pages syscall32_setup_pages
+extern int sysctl_ldt16;
#endif
/*
@@ -249,6 +250,13 @@ static struct ctl_table abi_table2[] = {
.mode = 0644,
.proc_handler = proc_dointvec
},
+ {
+ .procname = "ldt16",
+ .data = &sysctl_ldt16,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec
+ },
{}
};
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 201d09a7c46b..f17b29210ac4 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -1339,6 +1339,7 @@ xen_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
static struct notifier_block xen_panic_block = {
.notifier_call= xen_panic_event,
+ .priority = INT_MIN
};
int xen_panic_handler_init(void)
@@ -1515,7 +1516,7 @@ static void __init xen_pvh_early_guest_init(void)
}
/* First C function to be called on Xen boot */
-asmlinkage void __init xen_start_kernel(void)
+asmlinkage __visible void __init xen_start_kernel(void)
{
struct physdev_set_iopl set_iopl;
int rc;
diff --git a/arch/x86/xen/irq.c b/arch/x86/xen/irq.c
index 08f763de26fe..a1207cb6472a 100644
--- a/arch/x86/xen/irq.c
+++ b/arch/x86/xen/irq.c
@@ -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;
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 86e02eabb640..6f6e15d28466 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -2510,6 +2510,95 @@ void __init xen_hvm_init_mmu_ops(void)
}
#endif
+#ifdef CONFIG_XEN_PVH
+/*
+ * Map foreign gfn (fgfn), to local pfn (lpfn). This for the user
+ * space creating new guest on pvh dom0 and needing to map domU pages.
+ */
+static int xlate_add_to_p2m(unsigned long lpfn, unsigned long fgfn,
+ unsigned int domid)
+{
+ int rc, err = 0;
+ xen_pfn_t gpfn = lpfn;
+ xen_ulong_t idx = fgfn;
+
+ struct xen_add_to_physmap_range xatp = {
+ .domid = DOMID_SELF,
+ .foreign_domid = domid,
+ .size = 1,
+ .space = XENMAPSPACE_gmfn_foreign,
+ };
+ set_xen_guest_handle(xatp.idxs, &idx);
+ set_xen_guest_handle(xatp.gpfns, &gpfn);
+ set_xen_guest_handle(xatp.errs, &err);
+
+ rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap_range, &xatp);
+ if (rc < 0)
+ return rc;
+ return err;
+}
+
+static int xlate_remove_from_p2m(unsigned long spfn, int count)
+{
+ struct xen_remove_from_physmap xrp;
+ int i, rc;
+
+ for (i = 0; i < count; i++) {
+ xrp.domid = DOMID_SELF;
+ xrp.gpfn = spfn+i;
+ rc = HYPERVISOR_memory_op(XENMEM_remove_from_physmap, &xrp);
+ if (rc)
+ break;
+ }
+ return rc;
+}
+
+struct xlate_remap_data {
+ unsigned long fgfn; /* foreign domain's gfn */
+ pgprot_t prot;
+ domid_t domid;
+ int index;
+ struct page **pages;
+};
+
+static int xlate_map_pte_fn(pte_t *ptep, pgtable_t token, unsigned long addr,
+ void *data)
+{
+ int rc;
+ struct xlate_remap_data *remap = data;
+ unsigned long pfn = page_to_pfn(remap->pages[remap->index++]);
+ pte_t pteval = pte_mkspecial(pfn_pte(pfn, remap->prot));
+
+ rc = xlate_add_to_p2m(pfn, remap->fgfn, remap->domid);
+ if (rc)
+ return rc;
+ native_set_pte(ptep, pteval);
+
+ return 0;
+}
+
+static int xlate_remap_gfn_range(struct vm_area_struct *vma,
+ unsigned long addr, unsigned long mfn,
+ int nr, pgprot_t prot, unsigned domid,
+ struct page **pages)
+{
+ int err;
+ struct xlate_remap_data pvhdata;
+
+ BUG_ON(!pages);
+
+ pvhdata.fgfn = mfn;
+ pvhdata.prot = prot;
+ pvhdata.domid = domid;
+ pvhdata.index = 0;
+ pvhdata.pages = pages;
+ err = apply_to_page_range(vma->vm_mm, addr, nr << PAGE_SHIFT,
+ xlate_map_pte_fn, &pvhdata);
+ flush_tlb_all();
+ return err;
+}
+#endif
+
#define REMAP_BATCH_SIZE 16
struct remap_data {
@@ -2522,7 +2611,7 @@ static int remap_area_mfn_pte_fn(pte_t *ptep, pgtable_t token,
unsigned long addr, void *data)
{
struct remap_data *rmd = data;
- pte_t pte = pte_mkspecial(pfn_pte(rmd->mfn++, rmd->prot));
+ pte_t pte = pte_mkspecial(mfn_pte(rmd->mfn++, rmd->prot));
rmd->mmu_update->ptr = virt_to_machine(ptep).maddr;
rmd->mmu_update->val = pte_val_ma(pte);
@@ -2544,13 +2633,18 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
unsigned long range;
int err = 0;
- if (xen_feature(XENFEAT_auto_translated_physmap))
- return -EINVAL;
-
- prot = __pgprot(pgprot_val(prot) | _PAGE_IOMAP);
-
BUG_ON(!((vma->vm_flags & (VM_PFNMAP | VM_IO)) == (VM_PFNMAP | VM_IO)));
+ if (xen_feature(XENFEAT_auto_translated_physmap)) {
+#ifdef CONFIG_XEN_PVH
+ /* We need to update the local page tables and the xen HAP */
+ return xlate_remap_gfn_range(vma, addr, mfn, nr, prot,
+ domid, pages);
+#else
+ return -EINVAL;
+#endif
+ }
+
rmd.mfn = mfn;
rmd.prot = prot;
@@ -2588,6 +2682,25 @@ int xen_unmap_domain_mfn_range(struct vm_area_struct *vma,
if (!pages || !xen_feature(XENFEAT_auto_translated_physmap))
return 0;
+#ifdef CONFIG_XEN_PVH
+ while (numpgs--) {
+ /*
+ * The mmu has already cleaned up the process mmu
+ * resources at this point (lookup_address will return
+ * NULL).
+ */
+ unsigned long pfn = page_to_pfn(pages[numpgs]);
+
+ xlate_remove_from_p2m(pfn, 1);
+ }
+ /*
+ * We don't need to flush tlbs because as part of
+ * xlate_remove_from_p2m, the hypervisor will do tlb flushes
+ * after removing the p2m entries from the EPT/NPT
+ */
+ return 0;
+#else
return -EINVAL;
+#endif
}
EXPORT_SYMBOL_GPL(xen_unmap_domain_mfn_range);
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c
index 85e5d78c9874..9bb3d82ffec8 100644
--- a/arch/x86/xen/p2m.c
+++ b/arch/x86/xen/p2m.c
@@ -36,7 +36,7 @@
* pfn_to_mfn(0xc0000)=0xc0000
*
* The benefit of this is, that we can assume for non-RAM regions (think
- * PCI BARs, or ACPI spaces), we can create mappings easily b/c we
+ * PCI BARs, or ACPI spaces), we can create mappings easily because we
* get the PFN value to match the MFN.
*
* For this to work efficiently we have one new page p2m_identity and
@@ -60,7 +60,7 @@
* There is also a digram of the P2M at the end that can help.
* Imagine your E820 looking as so:
*
- * 1GB 2GB
+ * 1GB 2GB 4GB
* /-------------------+---------\/----\ /----------\ /---+-----\
* | System RAM | Sys RAM ||ACPI| | reserved | | Sys RAM |
* \-------------------+---------/\----/ \----------/ \---+-----/
@@ -77,9 +77,8 @@
* of the PFN and the end PFN (263424 and 512256 respectively). The first step
* is to reserve_brk a top leaf page if the p2m[1] is missing. The top leaf page
* covers 512^2 of page estate (1GB) and in case the start or end PFN is not
- * aligned on 512^2*PAGE_SIZE (1GB) we loop on aligned 1GB PFNs from start pfn
- * to end pfn. We reserve_brk top leaf pages if they are missing (means they
- * point to p2m_mid_missing).
+ * aligned on 512^2*PAGE_SIZE (1GB) we reserve_brk new middle and leaf pages as
+ * required to split any existing p2m_mid_missing middle pages.
*
* With the E820 example above, 263424 is not 1GB aligned so we allocate a
* reserve_brk page which will cover the PFNs estate from 0x40000 to 0x80000.
@@ -88,7 +87,7 @@
* Next stage is to determine if we need to do a more granular boundary check
* on the 4MB (or 2MB depending on architecture) off the start and end pfn's.
* We check if the start pfn and end pfn violate that boundary check, and if
- * so reserve_brk a middle (p2m[x][y]) leaf page. This way we have a much finer
+ * so reserve_brk a (p2m[x][y]) leaf page. This way we have a much finer
* granularity of setting which PFNs are missing and which ones are identity.
* In our example 263424 and 512256 both fail the check so we reserve_brk two
* pages. Populate them with INVALID_P2M_ENTRY (so they both have "missing"
@@ -102,9 +101,10 @@
*
* The next step is to walk from the start pfn to the end pfn setting
* the IDENTITY_FRAME_BIT on each PFN. This is done in set_phys_range_identity.
- * If we find that the middle leaf is pointing to p2m_missing we can swap it
- * over to p2m_identity - this way covering 4MB (or 2MB) PFN space. At this
- * point we do not need to worry about boundary aligment (so no need to
+ * If we find that the middle entry is pointing to p2m_missing we can swap it
+ * over to p2m_identity - this way covering 4MB (or 2MB) PFN space (and
+ * similarly swapping p2m_mid_missing for p2m_mid_identity for larger regions).
+ * At this point we do not need to worry about boundary aligment (so no need to
* reserve_brk a middle page, figure out which PFNs are "missing" and which
* ones are identity), as that has been done earlier. If we find that the
* middle leaf is not occupied by p2m_identity or p2m_missing, we dereference
@@ -118,6 +118,9 @@
* considered missing). In our case, p2m[1][2][0->255] and p2m[1][488][257->511]
* contain the INVALID_P2M_ENTRY value and are considered "missing."
*
+ * Finally, the region beyond the end of of the E820 (4 GB in this example)
+ * is set to be identity (in case there are MMIO regions placed here).
+ *
* This is what the p2m ends up looking (for the E820 above) with this
* fabulous drawing:
*
@@ -129,21 +132,27 @@
* |-----| \ | [p2m_identity]+\\ | .... |
* | 2 |--\ \-------------------->| ... | \\ \----------------/
* |-----| \ \---------------/ \\
- * | 3 |\ \ \\ p2m_identity
- * |-----| \ \-------------------->/---------------\ /-----------------\
- * | .. +->+ | [p2m_identity]+-->| ~0, ~0, ~0, ... |
- * \-----/ / | [p2m_identity]+-->| ..., ~0 |
- * / /---------------\ | .... | \-----------------/
- * / | IDENTITY[@0] | /-+-[x], ~0, ~0.. |
- * / | IDENTITY[@256]|<----/ \---------------/
- * / | ~0, ~0, .... |
- * | \---------------/
- * |
- * p2m_mid_missing p2m_missing
- * /-----------------\ /------------\
- * | [p2m_missing] +---->| ~0, ~0, ~0 |
- * | [p2m_missing] +---->| ..., ~0 |
- * \-----------------/ \------------/
+ * | 3 |-\ \ \\ p2m_identity [1]
+ * |-----| \ \-------------------->/---------------\ /-----------------\
+ * | .. |\ | | [p2m_identity]+-->| ~0, ~0, ~0, ... |
+ * \-----/ | | | [p2m_identity]+-->| ..., ~0 |
+ * | | | .... | \-----------------/
+ * | | +-[x], ~0, ~0.. +\
+ * | | \---------------/ \
+ * | | \-> /---------------\
+ * | V p2m_mid_missing p2m_missing | IDENTITY[@0] |
+ * | /-----------------\ /------------\ | IDENTITY[@256]|
+ * | | [p2m_missing] +---->| ~0, ~0, ...| | ~0, ~0, .... |
+ * | | [p2m_missing] +---->| ..., ~0 | \---------------/
+ * | | ... | \------------/
+ * | \-----------------/
+ * |
+ * | p2m_mid_identity
+ * | /-----------------\
+ * \-->| [p2m_identity] +---->[1]
+ * | [p2m_identity] +---->[1]
+ * | ... |
+ * \-----------------/
*
* where ~0 is INVALID_P2M_ENTRY. IDENTITY is (PFN | IDENTITY_BIT)
*/
@@ -187,13 +196,15 @@ static RESERVE_BRK_ARRAY(unsigned long, p2m_top_mfn, P2M_TOP_PER_PAGE);
static RESERVE_BRK_ARRAY(unsigned long *, p2m_top_mfn_p, P2M_TOP_PER_PAGE);
static RESERVE_BRK_ARRAY(unsigned long, p2m_identity, P2M_PER_PAGE);
+static RESERVE_BRK_ARRAY(unsigned long *, p2m_mid_identity, P2M_MID_PER_PAGE);
+static RESERVE_BRK_ARRAY(unsigned long, p2m_mid_identity_mfn, P2M_MID_PER_PAGE);
RESERVE_BRK(p2m_mid, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE)));
RESERVE_BRK(p2m_mid_mfn, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE)));
/* We might hit two boundary violations at the start and end, at max each
* boundary violation will require three middle nodes. */
-RESERVE_BRK(p2m_mid_identity, PAGE_SIZE * 2 * 3);
+RESERVE_BRK(p2m_mid_extra, PAGE_SIZE * 2 * 3);
/* When we populate back during bootup, the amount of pages can vary. The
* max we have is seen is 395979, but that does not mean it can't be more.
@@ -242,20 +253,20 @@ static void p2m_top_mfn_p_init(unsigned long **top)
top[i] = p2m_mid_missing_mfn;
}
-static void p2m_mid_init(unsigned long **mid)
+static void p2m_mid_init(unsigned long **mid, unsigned long *leaf)
{
unsigned i;
for (i = 0; i < P2M_MID_PER_PAGE; i++)
- mid[i] = p2m_missing;
+ mid[i] = leaf;
}
-static void p2m_mid_mfn_init(unsigned long *mid)
+static void p2m_mid_mfn_init(unsigned long *mid, unsigned long *leaf)
{
unsigned i;
for (i = 0; i < P2M_MID_PER_PAGE; i++)
- mid[i] = virt_to_mfn(p2m_missing);
+ mid[i] = virt_to_mfn(leaf);
}
static void p2m_init(unsigned long *p2m)
@@ -286,7 +297,9 @@ void __ref xen_build_mfn_list_list(void)
/* Pre-initialize p2m_top_mfn to be completely missing */
if (p2m_top_mfn == NULL) {
p2m_mid_missing_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE);
- p2m_mid_mfn_init(p2m_mid_missing_mfn);
+ p2m_mid_mfn_init(p2m_mid_missing_mfn, p2m_missing);
+ p2m_mid_identity_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE);
+ p2m_mid_mfn_init(p2m_mid_identity_mfn, p2m_identity);
p2m_top_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE);
p2m_top_mfn_p_init(p2m_top_mfn_p);
@@ -295,7 +308,8 @@ void __ref xen_build_mfn_list_list(void)
p2m_top_mfn_init(p2m_top_mfn);
} else {
/* Reinitialise, mfn's all change after migration */
- p2m_mid_mfn_init(p2m_mid_missing_mfn);
+ p2m_mid_mfn_init(p2m_mid_missing_mfn, p2m_missing);
+ p2m_mid_mfn_init(p2m_mid_identity_mfn, p2m_identity);
}
for (pfn = 0; pfn < xen_max_p2m_pfn; pfn += P2M_PER_PAGE) {
@@ -327,7 +341,7 @@ void __ref xen_build_mfn_list_list(void)
* it too late.
*/
mid_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE);
- p2m_mid_mfn_init(mid_mfn_p);
+ p2m_mid_mfn_init(mid_mfn_p, p2m_missing);
p2m_top_mfn_p[topidx] = mid_mfn_p;
}
@@ -365,16 +379,17 @@ void __init xen_build_dynamic_phys_to_machine(void)
p2m_missing = extend_brk(PAGE_SIZE, PAGE_SIZE);
p2m_init(p2m_missing);
+ p2m_identity = extend_brk(PAGE_SIZE, PAGE_SIZE);
+ p2m_init(p2m_identity);
p2m_mid_missing = extend_brk(PAGE_SIZE, PAGE_SIZE);
- p2m_mid_init(p2m_mid_missing);
+ p2m_mid_init(p2m_mid_missing, p2m_missing);
+ p2m_mid_identity = extend_brk(PAGE_SIZE, PAGE_SIZE);
+ p2m_mid_init(p2m_mid_identity, p2m_identity);
p2m_top = extend_brk(PAGE_SIZE, PAGE_SIZE);
p2m_top_init(p2m_top);
- p2m_identity = extend_brk(PAGE_SIZE, PAGE_SIZE);
- p2m_init(p2m_identity);
-
/*
* The domain builder gives us a pre-constructed p2m array in
* mfn_list for all the pages initially given to us, so we just
@@ -386,7 +401,7 @@ void __init xen_build_dynamic_phys_to_machine(void)
if (p2m_top[topidx] == p2m_mid_missing) {
unsigned long **mid = extend_brk(PAGE_SIZE, PAGE_SIZE);
- p2m_mid_init(mid);
+ p2m_mid_init(mid, p2m_missing);
p2m_top[topidx] = mid;
}
@@ -492,7 +507,7 @@ unsigned long get_phys_to_machine(unsigned long pfn)
unsigned topidx, mididx, idx;
if (unlikely(pfn >= MAX_P2M_PFN))
- return INVALID_P2M_ENTRY;
+ return IDENTITY_FRAME(pfn);
topidx = p2m_top_index(pfn);
mididx = p2m_mid_index(pfn);
@@ -545,7 +560,7 @@ static bool alloc_p2m(unsigned long pfn)
if (!mid)
return false;
- p2m_mid_init(mid);
+ p2m_mid_init(mid, p2m_missing);
if (cmpxchg(top_p, p2m_mid_missing, mid) != p2m_mid_missing)
free_p2m_page(mid);
@@ -565,7 +580,7 @@ static bool alloc_p2m(unsigned long pfn)
if (!mid_mfn)
return false;
- p2m_mid_mfn_init(mid_mfn);
+ p2m_mid_mfn_init(mid_mfn, p2m_missing);
missing_mfn = virt_to_mfn(p2m_mid_missing_mfn);
mid_mfn_mfn = virt_to_mfn(mid_mfn);
@@ -596,7 +611,7 @@ static bool alloc_p2m(unsigned long pfn)
return true;
}
-static bool __init early_alloc_p2m_middle(unsigned long pfn, bool check_boundary)
+static bool __init early_alloc_p2m(unsigned long pfn, bool check_boundary)
{
unsigned topidx, mididx, idx;
unsigned long *p2m;
@@ -638,7 +653,7 @@ static bool __init early_alloc_p2m_middle(unsigned long pfn, bool check_boundary
return true;
}
-static bool __init early_alloc_p2m(unsigned long pfn)
+static bool __init early_alloc_p2m_middle(unsigned long pfn)
{
unsigned topidx = p2m_top_index(pfn);
unsigned long *mid_mfn_p;
@@ -649,7 +664,7 @@ static bool __init early_alloc_p2m(unsigned long pfn)
if (mid == p2m_mid_missing) {
mid = extend_brk(PAGE_SIZE, PAGE_SIZE);
- p2m_mid_init(mid);
+ p2m_mid_init(mid, p2m_missing);
p2m_top[topidx] = mid;
@@ -658,12 +673,12 @@ static bool __init early_alloc_p2m(unsigned long pfn)
/* And the save/restore P2M tables.. */
if (mid_mfn_p == p2m_mid_missing_mfn) {
mid_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE);
- p2m_mid_mfn_init(mid_mfn_p);
+ p2m_mid_mfn_init(mid_mfn_p, p2m_missing);
p2m_top_mfn_p[topidx] = mid_mfn_p;
p2m_top_mfn[topidx] = virt_to_mfn(mid_mfn_p);
/* Note: we don't set mid_mfn_p[midix] here,
- * look in early_alloc_p2m_middle */
+ * look in early_alloc_p2m() */
}
return true;
}
@@ -739,7 +754,7 @@ found:
/* This shouldn't happen */
if (WARN_ON(p2m_top[topidx] == p2m_mid_missing))
- early_alloc_p2m(set_pfn);
+ early_alloc_p2m_middle(set_pfn);
if (WARN_ON(p2m_top[topidx][mididx] != p2m_missing))
return false;
@@ -754,13 +769,13 @@ found:
bool __init early_set_phys_to_machine(unsigned long pfn, unsigned long mfn)
{
if (unlikely(!__set_phys_to_machine(pfn, mfn))) {
- if (!early_alloc_p2m(pfn))
+ if (!early_alloc_p2m_middle(pfn))
return false;
if (early_can_reuse_p2m_middle(pfn, mfn))
return __set_phys_to_machine(pfn, mfn);
- if (!early_alloc_p2m_middle(pfn, false /* boundary crossover OK!*/))
+ if (!early_alloc_p2m(pfn, false /* boundary crossover OK!*/))
return false;
if (!__set_phys_to_machine(pfn, mfn))
@@ -769,12 +784,30 @@ bool __init early_set_phys_to_machine(unsigned long pfn, unsigned long mfn)
return true;
}
+
+static void __init early_split_p2m(unsigned long pfn)
+{
+ unsigned long mididx, idx;
+
+ mididx = p2m_mid_index(pfn);
+ idx = p2m_index(pfn);
+
+ /*
+ * Allocate new middle and leaf pages if this pfn lies in the
+ * middle of one.
+ */
+ if (mididx || idx)
+ early_alloc_p2m_middle(pfn);
+ if (idx)
+ early_alloc_p2m(pfn, false);
+}
+
unsigned long __init set_phys_range_identity(unsigned long pfn_s,
unsigned long pfn_e)
{
unsigned long pfn;
- if (unlikely(pfn_s >= MAX_P2M_PFN || pfn_e >= MAX_P2M_PFN))
+ if (unlikely(pfn_s >= MAX_P2M_PFN))
return 0;
if (unlikely(xen_feature(XENFEAT_auto_translated_physmap)))
@@ -783,19 +816,30 @@ unsigned long __init set_phys_range_identity(unsigned long pfn_s,
if (pfn_s > pfn_e)
return 0;
- for (pfn = (pfn_s & ~(P2M_MID_PER_PAGE * P2M_PER_PAGE - 1));
- pfn < ALIGN(pfn_e, (P2M_MID_PER_PAGE * P2M_PER_PAGE));
- pfn += P2M_MID_PER_PAGE * P2M_PER_PAGE)
- {
- WARN_ON(!early_alloc_p2m(pfn));
- }
+ if (pfn_e > MAX_P2M_PFN)
+ pfn_e = MAX_P2M_PFN;
- early_alloc_p2m_middle(pfn_s, true);
- early_alloc_p2m_middle(pfn_e, true);
+ early_split_p2m(pfn_s);
+ early_split_p2m(pfn_e);
+
+ for (pfn = pfn_s; pfn < pfn_e;) {
+ unsigned topidx = p2m_top_index(pfn);
+ unsigned mididx = p2m_mid_index(pfn);
- for (pfn = pfn_s; pfn < pfn_e; pfn++)
if (!__set_phys_to_machine(pfn, IDENTITY_FRAME(pfn)))
break;
+ pfn++;
+
+ /*
+ * If the PFN was set to a middle or leaf identity
+ * page the remainder must also be identity, so skip
+ * ahead to the next middle or leaf entry.
+ */
+ if (p2m_top[topidx] == p2m_mid_identity)
+ pfn = ALIGN(pfn, P2M_MID_PER_PAGE * P2M_PER_PAGE);
+ else if (p2m_top[topidx][mididx] == p2m_identity)
+ pfn = ALIGN(pfn, P2M_PER_PAGE);
+ }
if (!WARN((pfn - pfn_s) != (pfn_e - pfn_s),
"Identity mapping failed. We are %ld short of 1-1 mappings!\n",
@@ -825,8 +869,22 @@ bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn)
/* For sparse holes were the p2m leaf has real PFN along with
* PCI holes, stick in the PFN as the MFN value.
+ *
+ * set_phys_range_identity() will have allocated new middle
+ * and leaf pages as required so an existing p2m_mid_missing
+ * or p2m_missing mean that whole range will be identity so
+ * these can be switched to p2m_mid_identity or p2m_identity.
*/
if (mfn != INVALID_P2M_ENTRY && (mfn & IDENTITY_FRAME_BIT)) {
+ if (p2m_top[topidx] == p2m_mid_identity)
+ return true;
+
+ if (p2m_top[topidx] == p2m_mid_missing) {
+ WARN_ON(cmpxchg(&p2m_top[topidx], p2m_mid_missing,
+ p2m_mid_identity) != p2m_mid_missing);
+ return true;
+ }
+
if (p2m_top[topidx][mididx] == p2m_identity)
return true;
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
index 0982233b9b84..210426a26cc0 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -89,10 +89,10 @@ static void __init xen_add_extra_mem(u64 start, u64 size)
for (pfn = PFN_DOWN(start); pfn < xen_max_p2m_pfn; pfn++) {
unsigned long mfn = pfn_to_mfn(pfn);
- if (WARN(mfn == pfn, "Trying to over-write 1-1 mapping (pfn: %lx)\n", pfn))
+ if (WARN_ONCE(mfn == pfn, "Trying to over-write 1-1 mapping (pfn: %lx)\n", pfn))
continue;
- WARN(mfn != INVALID_P2M_ENTRY, "Trying to remove %lx which has %lx mfn!\n",
- pfn, mfn);
+ WARN_ONCE(mfn != INVALID_P2M_ENTRY, "Trying to remove %lx which has %lx mfn!\n",
+ pfn, mfn);
__set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
}
@@ -469,6 +469,15 @@ char * __init xen_memory_setup(void)
}
/*
+ * Set the rest as identity mapped, in case PCI BARs are
+ * located here.
+ *
+ * PFNs above MAX_P2M_PFN are considered identity mapped as
+ * well.
+ */
+ set_phys_range_identity(map[i-1].addr / PAGE_SIZE, ~0ul);
+
+ /*
* In domU, the ISA region is normal, usable memory, but we
* reserve ISA memory anyway because too many things poke
* about in there.
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index a18eadd8bb40..7005974c3ff3 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -441,10 +441,11 @@ static int xen_cpu_up(unsigned int cpu, struct task_struct *idle)
irq_ctx_init(cpu);
#else
clear_tsk_thread_flag(idle, TIF_FORK);
+#endif
per_cpu(kernel_stack, cpu) =
(unsigned long)task_stack_page(idle) -
KERNEL_STACK_OFFSET + THREAD_SIZE;
-#endif
+
xen_setup_runstate_info(cpu);
xen_setup_timer(cpu);
xen_init_lock_cpu(cpu);
diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c
index 4d3acc34a998..0ba5f3b967f0 100644
--- a/arch/x86/xen/spinlock.c
+++ b/arch/x86/xen/spinlock.c
@@ -274,7 +274,7 @@ void __init xen_init_spinlocks(void)
printk(KERN_DEBUG "xen: PV spinlocks disabled\n");
return;
}
-
+ printk(KERN_DEBUG "xen: PV spinlocks enabled\n");
pv_lock_ops.lock_spinning = PV_CALLEE_SAVE(xen_lock_spinning);
pv_lock_ops.unlock_kick = xen_unlock_kick;
}
@@ -290,6 +290,9 @@ static __init int xen_init_spinlocks_jump(void)
if (!xen_pvspin)
return 0;
+ if (!xen_domain())
+ return 0;
+
static_key_slow_inc(&paravirt_ticketlocks_enabled);
return 0;
}
diff --git a/arch/x86/xen/suspend.c b/arch/x86/xen/suspend.c
index 45329c8c226e..c4df9dbd63b7 100644
--- a/arch/x86/xen/suspend.c
+++ b/arch/x86/xen/suspend.c
@@ -12,8 +12,10 @@
#include "xen-ops.h"
#include "mmu.h"
-void xen_arch_pre_suspend(void)
+static void xen_pv_pre_suspend(void)
{
+ xen_mm_pin_all();
+
xen_start_info->store_mfn = mfn_to_pfn(xen_start_info->store_mfn);
xen_start_info->console.domU.mfn =
mfn_to_pfn(xen_start_info->console.domU.mfn);
@@ -26,7 +28,7 @@ void xen_arch_pre_suspend(void)
BUG();
}
-void xen_arch_hvm_post_suspend(int suspend_cancelled)
+static void xen_hvm_post_suspend(int suspend_cancelled)
{
#ifdef CONFIG_XEN_PVHVM
int cpu;
@@ -41,7 +43,7 @@ void xen_arch_hvm_post_suspend(int suspend_cancelled)
#endif
}
-void xen_arch_post_suspend(int suspend_cancelled)
+static void xen_pv_post_suspend(int suspend_cancelled)
{
xen_build_mfn_list_list();
@@ -60,6 +62,21 @@ void xen_arch_post_suspend(int suspend_cancelled)
xen_vcpu_restore();
}
+ xen_mm_unpin_all();
+}
+
+void xen_arch_pre_suspend(void)
+{
+ if (xen_pv_domain())
+ xen_pv_pre_suspend();
+}
+
+void xen_arch_post_suspend(int cancelled)
+{
+ if (xen_pv_domain())
+ xen_pv_post_suspend(cancelled);
+ else
+ xen_hvm_post_suspend(cancelled);
}
static void xen_vcpu_notify_restore(void *data)
diff --git a/arch/x86/xen/xen-asm_32.S b/arch/x86/xen/xen-asm_32.S
index 33ca6e42a4ca..fd92a64d748e 100644
--- a/arch/x86/xen/xen-asm_32.S
+++ b/arch/x86/xen/xen-asm_32.S
@@ -75,6 +75,17 @@ ENDPROC(xen_sysexit)
* stack state in whatever form its in, we keep things simple by only
* using a single register which is pushed/popped on the stack.
*/
+
+.macro POP_FS
+1:
+ popw %fs
+.pushsection .fixup, "ax"
+2: movw $0, (%esp)
+ jmp 1b
+.popsection
+ _ASM_EXTABLE(1b,2b)
+.endm
+
ENTRY(xen_iret)
/* test eflags for special cases */
testl $(X86_EFLAGS_VM | XEN_EFLAGS_NMI), 8(%esp)
@@ -83,15 +94,13 @@ ENTRY(xen_iret)
push %eax
ESP_OFFSET=4 # bytes pushed onto stack
- /*
- * Store vcpu_info pointer for easy access. Do it this way to
- * avoid having to reload %fs
- */
+ /* Store vcpu_info pointer for easy access */
#ifdef CONFIG_SMP
- GET_THREAD_INFO(%eax)
- movl %ss:TI_cpu(%eax), %eax
- movl %ss:__per_cpu_offset(,%eax,4), %eax
- mov %ss:xen_vcpu(%eax), %eax
+ pushw %fs
+ movl $(__KERNEL_PERCPU), %eax
+ movl %eax, %fs
+ movl %fs:xen_vcpu, %eax
+ POP_FS
#else
movl %ss:xen_vcpu, %eax
#endif
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index 1cb6f4c37300..c834d4b231f0 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -31,6 +31,8 @@ void xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn);
void xen_reserve_top(void);
extern unsigned long xen_max_p2m_pfn;
+void xen_mm_pin_all(void);
+void xen_mm_unpin_all(void);
void xen_set_pat(u64);
char * __init xen_memory_setup(void);
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index 02d6d29a63c1..3a617af60d46 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -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
index 000000000000..742a347be67a
--- /dev/null
+++ b/arch/xtensa/boot/dts/kc705.dts
@@ -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
index 000000000000..d3a88e029873
--- /dev/null
+++ b/arch/xtensa/boot/dts/xtfpga-flash-128m.dtsi
@@ -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>;
+ };
+ };
+ };
+};
diff --git a/arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi b/arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi
index e5703c7beeb6..1d97203c18e7 100644
--- a/arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi
+++ b/arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi
@@ -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>;
- };
- };
+ };
};
diff --git a/arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi b/arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi
index 6f9c10d6b689..d1c621ca8be1 100644
--- a/arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi
+++ b/arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi
@@ -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>;
- };
- };
+ };
};
diff --git a/arch/xtensa/boot/dts/xtfpga.dtsi b/arch/xtensa/boot/dts/xtfpga.dtsi
index e7370b11348e..dec9178840f6 100644
--- a/arch/xtensa/boot/dts/xtfpga.dtsi
+++ b/arch/xtensa/boot/dts/xtfpga.dtsi
@@ -42,21 +42,28 @@
};
};
- 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>;
+ };
};
};
diff --git a/arch/xtensa/include/asm/bootparam.h b/arch/xtensa/include/asm/bootparam.h
index 23392c5630ce..892aab399ac8 100644
--- a/arch/xtensa/include/asm/bootparam.h
+++ b/arch/xtensa/include/asm/bootparam.h
@@ -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
index 000000000000..9f6c33d0428a
--- /dev/null
+++ b/arch/xtensa/include/asm/fixmap.h
@@ -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
diff --git a/arch/xtensa/include/asm/highmem.h b/arch/xtensa/include/asm/highmem.h
index 80be15124697..2653ef5d55f1 100644
--- a/arch/xtensa/include/asm/highmem.h
+++ b/arch/xtensa/include/asm/highmem.h
@@ -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
diff --git a/arch/xtensa/include/asm/pgtable.h b/arch/xtensa/include/asm/pgtable.h
index 216446295ada..4b0ca35a93b1 100644
--- a/arch/xtensa/include/asm/pgtable.h
+++ b/arch/xtensa/include/asm/pgtable.h
@@ -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
index 000000000000..c015c5c8e3f7
--- /dev/null
+++ b/arch/xtensa/include/asm/sysmem.h
@@ -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 */
diff --git a/arch/xtensa/include/asm/tlbflush.h b/arch/xtensa/include/asm/tlbflush.h
index fc34274ce41b..06875feb27c2 100644
--- a/arch/xtensa/include/asm/tlbflush.h
+++ b/arch/xtensa/include/asm/tlbflush.h
@@ -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 */
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
index 84fe931bb60e..9757bb74e532 100644
--- a/arch/xtensa/kernel/setup.c
+++ b/arch/xtensa/kernel/setup.c
@@ -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();
diff --git a/arch/xtensa/kernel/smp.c b/arch/xtensa/kernel/smp.c
index aa8bd8717927..40b5a3771fb0 100644
--- a/arch/xtensa/kernel/smp.c
+++ b/arch/xtensa/kernel/smp.c
@@ -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)
diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c
index 80b33ed51f31..4d2872fd9bb5 100644
--- a/arch/xtensa/kernel/xtensa_ksyms.c
+++ b/arch/xtensa/kernel/xtensa_ksyms.c
@@ -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
diff --git a/arch/xtensa/mm/Makefile b/arch/xtensa/mm/Makefile
index f0b646d2f843..f54f78e24d7b 100644
--- a/arch/xtensa/mm/Makefile
+++ b/arch/xtensa/mm/Makefile
@@ -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
diff --git a/arch/xtensa/mm/cache.c b/arch/xtensa/mm/cache.c
index ba4c47f291b1..63cbb867dadd 100644
--- a/arch/xtensa/mm/cache.c
+++ b/arch/xtensa/mm/cache.c
@@ -59,6 +59,10 @@
*
*/
+#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
index 000000000000..17a8c0d6fd17
--- /dev/null
+++ b/arch/xtensa/mm/highmem.c
@@ -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);
+}
diff --git a/arch/xtensa/mm/init.c b/arch/xtensa/mm/init.c
index aff108df92d3..4224256bb215 100644
--- a/arch/xtensa/mm/init.c
+++ b/arch/xtensa/mm/init.c
@@ -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>
@@ -27,11 +29,133 @@
#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,
@@ -39,53 +163,69 @@
* 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);
diff --git a/arch/xtensa/mm/mmu.c b/arch/xtensa/mm/mmu.c
index 861203e958da..3429b483d9f8 100644
--- a/arch/xtensa/mm/mmu.c
+++ b/arch/xtensa/mm/mmu.c
@@ -3,6 +3,7 @@
*
* Extracted from init.c
*/
+#include <linux/bootmem.h>
#include <linux/percpu.h>
#include <linux/init.h>
#include <linux/string.h>
@@ -16,9 +17,44 @@
#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
}
/*
diff --git a/arch/xtensa/mm/tlb.c b/arch/xtensa/mm/tlb.c
index ade623826788..5ece856c5725 100644
--- a/arch/xtensa/mm/tlb.c
+++ b/arch/xtensa/mm/tlb.c
@@ -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)
diff --git a/arch/xtensa/platforms/iss/Makefile b/arch/xtensa/platforms/iss/Makefile
index d2369b799c50..b3e89291cfba 100644
--- a/arch/xtensa/platforms/iss/Makefile
+++ b/arch/xtensa/platforms/iss/Makefile
@@ -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
diff --git a/arch/xtensa/platforms/xt2000/setup.c b/arch/xtensa/platforms/xt2000/setup.c
index f9bc87966290..b90555cb8089 100644
--- a/arch/xtensa/platforms/xt2000/setup.c
+++ b/arch/xtensa/platforms/xt2000/setup.c
@@ -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. */
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index e4a4145926f6..1039fb9ff5f5 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -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);
/*
diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c
index 1512e41cd93d..43665d0d0905 100644
--- a/crypto/crypto_user.c
+++ b/crypto/crypto_user.c
@@ -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) &&
diff --git a/drivers/Makefile b/drivers/Makefile
index e3ced91b1784..7183b6af5dac 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -53,8 +53,8 @@ obj-y += gpu/
obj-$(CONFIG_CONNECTOR) += connector/
# i810fb and intelfb depend on char/agp/
-obj-$(CONFIG_FB_I810) += video/i810/
-obj-$(CONFIG_FB_INTEL) += video/intelfb/
+obj-$(CONFIG_FB_I810) += video/fbdev/i810/
+obj-$(CONFIG_FB_INTEL) += video/fbdev/intelfb/
obj-$(CONFIG_PARPORT) += parport/
obj-y += base/ block/ misc/ mfd/ nfc/
@@ -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
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index ab686b310100..a34a22841002 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -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
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 0331f91d56e6..bce34afadcd0 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -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
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index 2c01c1da29ce..c67f6f5ad611 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -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);
diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c
index dbfe49e5fd63..1d4950388fa1 100644
--- a/drivers/acpi/acpi_platform.c
+++ b/drivers/acpi/acpi_platform.c
@@ -29,7 +29,6 @@ ACPI_MODULE_NAME("platform");
static const struct acpi_device_id acpi_platform_device_ids[] = {
{ "PNP0D40" },
- { "ACPI0003" },
{ "VPC2004" },
{ "BCM4752" },
diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c
index c29c2c3ec0ad..52c81c49cc7d 100644
--- a/drivers/acpi/acpi_processor.c
+++ b/drivers/acpi/acpi_processor.c
@@ -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)
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h
index 49bbc71fad54..a08a448068dd 100644
--- a/drivers/acpi/acpica/acglobal.h
+++ b/drivers/acpi/acpica/acglobal.h
@@ -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
diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c
index 68d97441432c..12878e1982f7 100644
--- a/drivers/acpi/acpica/exfield.c
+++ b/drivers/acpi/acpica/exfield.c
@@ -45,10 +45,71 @@
#include "accommon.h"
#include "acdispat.h"
#include "acinterp.h"
+#include "amlcode.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exfield")
+/* Local prototypes */
+static u32
+acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length);
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_get_serial_access_bytes
+ *
+ * PARAMETERS: accessor_type - The type of the protocol indicated by region
+ * field access attributes
+ * access_length - The access length of the region field
+ *
+ * RETURN: Decoded access length
+ *
+ * DESCRIPTION: This routine returns the length of the generic_serial_bus
+ * protocol bytes
+ *
+ ******************************************************************************/
+
+static u32
+acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length)
+{
+ u32 length;
+
+ switch (accessor_type) {
+ case AML_FIELD_ATTRIB_QUICK:
+
+ length = 0;
+ break;
+
+ case AML_FIELD_ATTRIB_SEND_RCV:
+ case AML_FIELD_ATTRIB_BYTE:
+
+ length = 1;
+ break;
+
+ case AML_FIELD_ATTRIB_WORD:
+ case AML_FIELD_ATTRIB_WORD_CALL:
+
+ length = 2;
+ break;
+
+ case AML_FIELD_ATTRIB_MULTIBYTE:
+ case AML_FIELD_ATTRIB_RAW_BYTES:
+ case AML_FIELD_ATTRIB_RAW_PROCESS:
+
+ length = access_length;
+ break;
+
+ case AML_FIELD_ATTRIB_BLOCK:
+ case AML_FIELD_ATTRIB_BLOCK_CALL:
+ default:
+
+ length = ACPI_GSBUS_BUFFER_SIZE;
+ break;
+ }
+
+ return (length);
+}
+
/*******************************************************************************
*
* FUNCTION: acpi_ex_read_data_from_field
@@ -63,8 +124,9 @@ ACPI_MODULE_NAME("exfield")
* Buffer, depending on the size of the field.
*
******************************************************************************/
+
acpi_status
-acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
+acpi_ex_read_data_from_field(struct acpi_walk_state * walk_state,
union acpi_operand_object *obj_desc,
union acpi_operand_object **ret_buffer_desc)
{
@@ -73,6 +135,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
acpi_size length;
void *buffer;
u32 function;
+ u16 accessor_type;
ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc);
@@ -116,9 +179,22 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
ACPI_READ | (obj_desc->field.attribute << 16);
} else if (obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_GSBUS) {
- length = ACPI_GSBUS_BUFFER_SIZE;
- function =
- ACPI_READ | (obj_desc->field.attribute << 16);
+ accessor_type = obj_desc->field.attribute;
+ length = acpi_ex_get_serial_access_length(accessor_type,
+ obj_desc->
+ field.
+ access_length);
+
+ /*
+ * Add additional 2 bytes for modeled generic_serial_bus data buffer:
+ * typedef struct {
+ * BYTEStatus; // Byte 0 of the data buffer
+ * BYTELength; // Byte 1 of the data buffer
+ * BYTE[x-1]Data; // Bytes 2-x of the arbitrary length data buffer,
+ * }
+ */
+ length += 2;
+ function = ACPI_READ | (accessor_type << 16);
} else { /* IPMI */
length = ACPI_IPMI_BUFFER_SIZE;
@@ -231,6 +307,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
void *buffer;
union acpi_operand_object *buffer_desc;
u32 function;
+ u16 accessor_type;
ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc);
@@ -284,9 +361,22 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
ACPI_WRITE | (obj_desc->field.attribute << 16);
} else if (obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_GSBUS) {
- length = ACPI_GSBUS_BUFFER_SIZE;
- function =
- ACPI_WRITE | (obj_desc->field.attribute << 16);
+ accessor_type = obj_desc->field.attribute;
+ length = acpi_ex_get_serial_access_length(accessor_type,
+ obj_desc->
+ field.
+ access_length);
+
+ /*
+ * Add additional 2 bytes for modeled generic_serial_bus data buffer:
+ * typedef struct {
+ * BYTEStatus; // Byte 0 of the data buffer
+ * BYTELength; // Byte 1 of the data buffer
+ * BYTE[x-1]Data; // Bytes 2-x of the arbitrary length data buffer,
+ * }
+ */
+ length += 2;
+ function = ACPI_WRITE | (accessor_type << 16);
} else { /* IPMI */
length = ACPI_IPMI_BUFFER_SIZE;
diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c
index a4702eee91a8..9fb85f38de90 100644
--- a/drivers/acpi/acpica/tbutils.c
+++ b/drivers/acpi/acpica/tbutils.c
@@ -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;
}
}
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 9a2c63b20050..6e7b2a12860d 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -36,6 +36,12 @@
#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
-------------------------------------------------------------------------- */
@@ -717,6 +744,279 @@ static void acpi_battery_refresh(struct acpi_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);
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c
index afec4526c48a..3d8413d02a97 100644
--- a/drivers/acpi/blacklist.c
+++ b/drivers/acpi/blacklist.c
@@ -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/bus.c b/drivers/acpi/bus.c
index e7e5844c87d0..cf925c4f36b7 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -380,9 +380,8 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
break;
default:
- acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type);
- ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY;
- goto err;
+ acpi_handle_debug(handle, "Unknown event type 0x%x\n", type);
+ break;
}
adev = acpi_bus_get_acpi_device(handle);
diff --git a/drivers/acpi/cm_sbs.c b/drivers/acpi/cm_sbs.c
new file mode 100644
index 000000000000..6c9ee68e46fb
--- /dev/null
+++ b/drivers/acpi/cm_sbs.c
@@ -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);
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index d7d32c28829b..ad11ba4a412d 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -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);
}
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index c1e31a41f949..25bbc55dca89 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -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;
}
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 8b6990e417ec..f8bc5a755dda 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -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"),
},
},
{
@@ -513,6 +513,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
},
{
.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",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 20e03a7eb8b4..0033fafc470b 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -116,7 +116,7 @@ config AHCI_ST
config AHCI_IMX
tristate "Freescale i.MX AHCI SATA support"
- depends on MFD_SYSCON
+ depends on MFD_SYSCON && (ARCH_MXC || COMPILE_TEST)
help
This option enables support for the Freescale i.MX SoC's
onboard AHCI SATA.
@@ -134,8 +134,7 @@ config AHCI_SUNXI
config AHCI_XGENE
tristate "APM X-Gene 6.0Gbps AHCI SATA host controller support"
- depends on ARM64 || COMPILE_TEST
- select PHY_XGENE
+ depends on PHY_XGENE
help
This option enables support for APM X-Gene SoC SATA host controller.
@@ -816,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.
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 5a0bf8ed649b..60707814a84b 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -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)
{
@@ -1164,9 +1175,9 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host)
#endif
static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports,
- struct ahci_host_priv *hpriv)
+ struct ahci_host_priv *hpriv)
{
- int nvec;
+ int rc, nvec;
if (hpriv->flags & AHCI_HFLAG_NO_MSI)
goto intx;
@@ -1183,12 +1194,19 @@ static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports,
if (nvec < n_ports)
goto single_msi;
- nvec = pci_enable_msi_range(pdev, nvec, nvec);
- if (nvec == -ENOSPC)
+ rc = pci_enable_msi_exact(pdev, nvec);
+ if (rc == -ENOSPC)
goto single_msi;
- else if (nvec < 0)
+ else if (rc < 0)
goto intx;
+ /* fallback to single MSI mode if the controller enforced MRSM mode */
+ if (readl(hpriv->mmio + HOST_CTL) & HOST_MRSM) {
+ pci_disable_msi(pdev);
+ printk(KERN_INFO "ahci: MRSM is on, fallback to single MSI\n");
+ goto single_msi;
+ }
+
return nvec;
single_msi:
@@ -1232,18 +1250,18 @@ int ahci_host_activate(struct ata_host *host, int irq, unsigned int n_msis)
return rc;
for (i = 0; i < host->n_ports; i++) {
- const char* desc;
struct ahci_port_priv *pp = host->ports[i]->private_data;
- /* pp is NULL for dummy ports */
- if (pp)
- desc = pp->irq_desc;
- else
- desc = dev_driver_string(host->dev);
+ /* Do not receive interrupts sent by dummy ports */
+ if (!pp) {
+ disable_irq(irq + i);
+ continue;
+ }
- rc = devm_request_threaded_irq(host->dev,
- irq + i, ahci_hw_interrupt, ahci_thread_fn, IRQF_SHARED,
- desc, host->ports[i]);
+ rc = devm_request_threaded_irq(host->dev, irq + i,
+ ahci_hw_interrupt,
+ ahci_thread_fn, IRQF_SHARED,
+ pp->irq_desc, host->ports[i]);
if (rc)
goto out_free_irqs;
}
@@ -1357,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);
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 51af275b3388..af63c75c2001 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -94,6 +94,7 @@ enum {
/* HOST_CTL bits */
HOST_RESET = (1 << 0), /* reset controller; self-clear */
HOST_IRQ_EN = (1 << 1), /* global IRQ enable */
+ HOST_MRSM = (1 << 2), /* MSI Revert to Single Message */
HOST_AHCI_EN = (1 << 31), /* AHCI enabled */
/* HOST_CAP bits */
@@ -235,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 */
diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c
index 497c7abe1c7d..8befeb69eeb1 100644
--- a/drivers/ata/ahci_imx.c
+++ b/drivers/ata/ahci_imx.c
@@ -29,9 +29,25 @@
#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)
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 6bd4f660b4e1..b9861453fc81 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -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;
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index c19734d96d7e..ea83828bfea9 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4224,8 +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*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, },
- { "Crucial_CT???M500SSD*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, },
+ { "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, },
/*
* Some WD SATA-I drives spin up and down erratically when the link
@@ -4792,21 +4794,26 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
{
struct ata_queued_cmd *qc = NULL;
- unsigned int i;
+ unsigned int i, tag;
/* no command while frozen */
if (unlikely(ap->pflags & ATA_PFLAG_FROZEN))
return NULL;
- /* the last tag is reserved for internal command. */
- for (i = 0; i < ATA_MAX_QUEUE - 1; i++)
- if (!test_and_set_bit(i, &ap->qc_allocated)) {
- qc = __ata_qc_from_tag(ap, i);
+ for (i = 0; i < ATA_MAX_QUEUE; i++) {
+ tag = (i + ap->last_tag + 1) % ATA_MAX_QUEUE;
+
+ /* the last tag is reserved for internal command. */
+ if (tag == ATA_TAG_INTERNAL)
+ continue;
+
+ if (!test_and_set_bit(tag, &ap->qc_allocated)) {
+ qc = __ata_qc_from_tag(ap, tag);
+ qc->tag = tag;
+ ap->last_tag = tag;
break;
}
-
- if (qc)
- qc->tag = i;
+ }
return qc;
}
@@ -6307,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;
@@ -6326,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++)
diff --git a/drivers/ata/pata_arasan_cf.c b/drivers/ata/pata_arasan_cf.c
index 6fac524c2f50..4edb1a81f63f 100644
--- a/drivers/ata/pata_arasan_cf.c
+++ b/drivers/ata/pata_arasan_cf.c
@@ -898,9 +898,12 @@ static int arasan_cf_probe(struct platform_device *pdev)
cf_card_detect(acdev, 0);
- return ata_host_activate(host, acdev->irq, irq_handler, 0,
- &arasan_cf_sht);
+ ret = ata_host_activate(host, acdev->irq, irq_handler, 0,
+ &arasan_cf_sht);
+ if (!ret)
+ return 0;
+ cf_exit(acdev);
free_clk:
clk_put(acdev->clk);
return ret;
diff --git a/drivers/ata/pata_at91.c b/drivers/ata/pata_at91.c
index e9c87274a781..8a66f23af4c4 100644
--- a/drivers/ata/pata_at91.c
+++ b/drivers/ata/pata_at91.c
@@ -407,12 +407,13 @@ static int pata_at91_probe(struct platform_device *pdev)
host->private_data = info;
- return ata_host_activate(host, gpio_is_valid(irq) ? gpio_to_irq(irq) : 0,
- gpio_is_valid(irq) ? ata_sff_interrupt : NULL,
- irq_flags, &pata_at91_sht);
+ ret = ata_host_activate(host, gpio_is_valid(irq) ? gpio_to_irq(irq) : 0,
+ gpio_is_valid(irq) ? ata_sff_interrupt : NULL,
+ irq_flags, &pata_at91_sht);
+ if (ret)
+ goto err_put;
- if (!ret)
- return 0;
+ return 0;
err_put:
clk_put(info->mck);
diff --git a/drivers/ata/pata_samsung_cf.c b/drivers/ata/pata_samsung_cf.c
index a79566d05666..0610e78c8a2a 100644
--- a/drivers/ata/pata_samsung_cf.c
+++ b/drivers/ata/pata_samsung_cf.c
@@ -594,9 +594,13 @@ static int __init pata_s3c_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, host);
- return ata_host_activate(host, info->irq,
- info->irq ? pata_s3c_irq : NULL,
- 0, &pata_s3c_sht);
+ ret = ata_host_activate(host, info->irq,
+ info->irq ? pata_s3c_irq : NULL,
+ 0, &pata_s3c_sht);
+ if (ret)
+ goto stop_clk;
+
+ return 0;
stop_clk:
clk_disable(info->clk);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 0dd65281cc65..20da3ad1696b 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -614,39 +614,6 @@ void device_remove_bin_file(struct device *dev,
}
EXPORT_SYMBOL_GPL(device_remove_bin_file);
-/**
- * device_schedule_callback_owner - helper to schedule a callback for a device
- * @dev: device.
- * @func: callback function to invoke later.
- * @owner: module owning the callback routine
- *
- * Attribute methods must not unregister themselves or their parent device
- * (which would amount to the same thing). Attempts to do so will deadlock,
- * since unregistration is mutually exclusive with driver callbacks.
- *
- * Instead methods can call this routine, which will attempt to allocate
- * and schedule a workqueue request to call back @func with @dev as its
- * argument in the workqueue's process context. @dev will be pinned until
- * @func returns.
- *
- * This routine is usually called via the inline device_schedule_callback(),
- * which automatically sets @owner to THIS_MODULE.
- *
- * Returns 0 if the request was submitted, -ENOMEM if storage could not
- * be allocated, -ENODEV if a reference to @owner isn't available.
- *
- * NOTE: This routine won't work if CONFIG_SYSFS isn't set! It uses an
- * underlying sysfs routine (since it is intended for use by attribute
- * methods), and if sysfs isn't available you'll get nothing but -ENOSYS.
- */
-int device_schedule_callback_owner(struct device *dev,
- void (*func)(struct device *), struct module *owner)
-{
- return sysfs_schedule_callback(&dev->kobj,
- (void (*)(void *)) func, dev, owner);
-}
-EXPORT_SYMBOL_GPL(device_schedule_callback_owner);
-
static void klist_children_get(struct klist_node *n)
{
struct device_private *p = to_device_private_parent(n);
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 06051767393f..62ec61e8f84a 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -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);
@@ -187,8 +200,8 @@ static void driver_bound(struct device *dev)
return;
}
- pr_debug("driver: '%s': %s: bound to device '%s'\n", dev_name(dev),
- __func__, dev->driver->name);
+ pr_debug("driver: '%s': %s: bound to device '%s'\n", dev->driver->name,
+ __func__, dev_name(dev));
klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices);
@@ -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
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index e714709704e4..5b47210889e0 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -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
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
index bbcbd3c43926..be7c1fb7c0c9 100644
--- a/drivers/base/topology.c
+++ b/drivers/base/topology.c
@@ -39,8 +39,7 @@
static ssize_t show_##name(struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
- unsigned int cpu = dev->id; \
- return sprintf(buf, "%d\n", topology_##name(cpu)); \
+ return sprintf(buf, "%d\n", topology_##name(dev->id)); \
}
#if defined(topology_thread_cpumask) || defined(topology_core_cpumask) || \
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index 7e8a55f8917c..2104b1b4ccda 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -1952,7 +1952,7 @@ static int __init atari_floppy_init (void)
goto Enomem;
}
TrackBuffer = DMABuffer + 512;
- PhysDMABuffer = virt_to_phys(DMABuffer);
+ PhysDMABuffer = atari_stram_to_phys(DMABuffer);
PhysTrackBuffer = virt_to_phys(TrackBuffer);
BufferDrive = BufferSide = BufferTrack = -1;
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 5f69c910c3ac..dc3a41c82b38 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -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)
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 16c21c0cb14d..c8f286e8d80f 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -147,11 +147,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, true);
+ spin_unlock_irqrestore(&vblk->vq_lock, flags);
}
static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req)
@@ -205,8 +205,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)
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index be571fef185d..a83b57e57b63 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -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 },
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index f338b0c5a8de..a7dfbf9a3afb 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -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);
diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c
index 293e2e0a0a87..00b73448b22e 100644
--- a/drivers/bus/mvebu-mbus.c
+++ b/drivers/bus/mvebu-mbus.c
@@ -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);
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index fbae63e3d304..6e9f74a5c095 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -40,7 +40,7 @@ config SGI_MBCS
source "drivers/tty/serial/Kconfig"
config TTY_PRINTK
- bool "TTY driver to output user messages via printk"
+ tristate "TTY driver to output user messages via printk"
depends on EXPERT && TTY
default n
---help---
diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c
index 8121b4c70ede..b29703324e94 100644
--- a/drivers/char/agp/frontend.c
+++ b/drivers/char/agp/frontend.c
@@ -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 |
diff --git a/drivers/char/hw_random/bcm2835-rng.c b/drivers/char/hw_random/bcm2835-rng.c
index 8c3b255e629a..e900961cdd2e 100644
--- a/drivers/char/hw_random/bcm2835-rng.c
+++ b/drivers/char/hw_random/bcm2835-rng.c
@@ -61,18 +61,18 @@ static int bcm2835_rng_probe(struct platform_device *pdev)
}
bcm2835_rng_ops.priv = (unsigned long)rng_base;
+ /* set warm-up count & enable */
+ __raw_writel(RNG_WARMUP_COUNT, rng_base + RNG_STATUS);
+ __raw_writel(RNG_RBGEN, rng_base + RNG_CTRL);
+
/* register driver */
err = hwrng_register(&bcm2835_rng_ops);
if (err) {
dev_err(dev, "hwrng registration failed\n");
iounmap(rng_base);
- } else {
+ } else
dev_info(dev, "hwrng registered\n");
- /* set warm-up count & enable */
- __raw_writel(RNG_WARMUP_COUNT, rng_base + RNG_STATUS);
- __raw_writel(RNG_RBGEN, rng_base + RNG_CTRL);
- }
return err;
}
diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig
index 0baa8fab4ea7..db1c9b7adaa6 100644
--- a/drivers/char/ipmi/Kconfig
+++ b/drivers/char/ipmi/Kconfig
@@ -50,6 +50,18 @@ config IPMI_SI
Currently, only KCS and SMIC are supported. If
you are using IPMI, you should probably say "y" here.
+config IPMI_SI_PROBE_DEFAULTS
+ bool 'Probe for all possible IPMI system interfaces by default'
+ default n
+ depends on IPMI_SI
+ help
+ Modern systems will usually expose IPMI interfaces via a discoverable
+ firmware mechanism such as ACPI or DMI. Older systems do not, and so
+ the driver is forced to probe hardware manually. This may cause boot
+ delays. Say "n" here to disable this manual probing. IPMI will then
+ only be available on older systems if the "ipmi_si_intf.trydefaults=1"
+ boot argument is passed.
+
config IPMI_WATCHDOG
tristate 'IPMI Watchdog Timer'
help
diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c
index f5e4cd7617f6..61e71616689b 100644
--- a/drivers/char/ipmi/ipmi_bt_sm.c
+++ b/drivers/char/ipmi/ipmi_bt_sm.c
@@ -352,7 +352,7 @@ static inline void write_all_bytes(struct si_sm_data *bt)
static inline int read_all_bytes(struct si_sm_data *bt)
{
- unsigned char i;
+ unsigned int i;
/*
* length is "framing info", minimum = 4: NetFn, Seq, Cmd, cCode.
diff --git a/drivers/char/ipmi/ipmi_kcs_sm.c b/drivers/char/ipmi/ipmi_kcs_sm.c
index 6a4bdc18955a..8c25f596808a 100644
--- a/drivers/char/ipmi/ipmi_kcs_sm.c
+++ b/drivers/char/ipmi/ipmi_kcs_sm.c
@@ -251,8 +251,9 @@ static inline int check_obf(struct si_sm_data *kcs, unsigned char status,
if (!GET_STATUS_OBF(status)) {
kcs->obf_timeout -= time;
if (kcs->obf_timeout < 0) {
- start_error_recovery(kcs, "OBF not ready in time");
- return 1;
+ kcs->obf_timeout = OBF_RETRY_TIMEOUT;
+ start_error_recovery(kcs, "OBF not ready in time");
+ return 1;
}
return 0;
}
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index ec4e10fcf1a5..e6db9381b2c7 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -55,6 +55,7 @@ static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void);
static int ipmi_init_msghandler(void);
static void smi_recv_tasklet(unsigned long);
static void handle_new_recv_msgs(ipmi_smi_t intf);
+static void need_waiter(ipmi_smi_t intf);
static int initialized;
@@ -73,14 +74,28 @@ static struct proc_dir_entry *proc_ipmi_root;
*/
#define MAX_MSG_TIMEOUT 60000
+/* Call every ~1000 ms. */
+#define IPMI_TIMEOUT_TIME 1000
+
+/* How many jiffies does it take to get to the timeout time. */
+#define IPMI_TIMEOUT_JIFFIES ((IPMI_TIMEOUT_TIME * HZ) / 1000)
+
+/*
+ * Request events from the queue every second (this is the number of
+ * IPMI_TIMEOUT_TIMES between event requests). Hopefully, in the
+ * future, IPMI will add a way to know immediately if an event is in
+ * the queue and this silliness can go away.
+ */
+#define IPMI_REQUEST_EV_TIME (1000 / (IPMI_TIMEOUT_TIME))
+
/*
* The main "user" data structure.
*/
struct ipmi_user {
struct list_head link;
- /* Set to "0" when the user is destroyed. */
- int valid;
+ /* Set to false when the user is destroyed. */
+ bool valid;
struct kref refcount;
@@ -92,7 +107,7 @@ struct ipmi_user {
ipmi_smi_t intf;
/* Does this interface receive IPMI events? */
- int gets_events;
+ bool gets_events;
};
struct cmd_rcvr {
@@ -383,6 +398,9 @@ struct ipmi_smi {
unsigned int waiting_events_count; /* How many events in queue? */
char delivering_events;
char event_msg_printed;
+ atomic_t event_waiters;
+ unsigned int ticks_to_req_ev;
+ int last_needs_timer;
/*
* The event receiver for my BMC, only really used at panic
@@ -395,7 +413,7 @@ struct ipmi_smi {
/* For handling of maintenance mode. */
int maintenance_mode;
- int maintenance_mode_enable;
+ bool maintenance_mode_enable;
int auto_maintenance_timeout;
spinlock_t maintenance_mode_lock; /* Used in a timer... */
@@ -451,7 +469,6 @@ static DEFINE_MUTEX(ipmi_interfaces_mutex);
static LIST_HEAD(smi_watchers);
static DEFINE_MUTEX(smi_watchers_mutex);
-
#define ipmi_inc_stat(intf, stat) \
atomic_inc(&(intf)->stats[IPMI_STAT_ ## stat])
#define ipmi_get_stat(intf, stat) \
@@ -772,6 +789,7 @@ static int intf_next_seq(ipmi_smi_t intf,
*seq = i;
*seqid = intf->seq_table[i].seqid;
intf->curr_seq = (i+1)%IPMI_IPMB_NUM_SEQ;
+ need_waiter(intf);
} else {
rv = -EAGAIN;
}
@@ -941,7 +959,7 @@ int ipmi_create_user(unsigned int if_num,
new_user->handler = handler;
new_user->handler_data = handler_data;
new_user->intf = intf;
- new_user->gets_events = 0;
+ new_user->gets_events = false;
if (!try_module_get(intf->handlers->owner)) {
rv = -ENODEV;
@@ -962,10 +980,15 @@ int ipmi_create_user(unsigned int if_num,
*/
mutex_unlock(&ipmi_interfaces_mutex);
- new_user->valid = 1;
+ new_user->valid = true;
spin_lock_irqsave(&intf->seq_lock, flags);
list_add_rcu(&new_user->link, &intf->users);
spin_unlock_irqrestore(&intf->seq_lock, flags);
+ if (handler->ipmi_watchdog_pretimeout) {
+ /* User wants pretimeouts, so make sure to watch for them. */
+ if (atomic_inc_return(&intf->event_waiters) == 1)
+ need_waiter(intf);
+ }
*user = new_user;
return 0;
@@ -1019,7 +1042,13 @@ int ipmi_destroy_user(ipmi_user_t user)
struct cmd_rcvr *rcvr;
struct cmd_rcvr *rcvrs = NULL;
- user->valid = 0;
+ user->valid = false;
+
+ if (user->handler->ipmi_watchdog_pretimeout)
+ atomic_dec(&intf->event_waiters);
+
+ if (user->gets_events)
+ atomic_dec(&intf->event_waiters);
/* Remove the user from the interface's sequence table. */
spin_lock_irqsave(&intf->seq_lock, flags);
@@ -1155,25 +1184,23 @@ int ipmi_set_maintenance_mode(ipmi_user_t user, int mode)
if (intf->maintenance_mode != mode) {
switch (mode) {
case IPMI_MAINTENANCE_MODE_AUTO:
- intf->maintenance_mode = mode;
intf->maintenance_mode_enable
= (intf->auto_maintenance_timeout > 0);
break;
case IPMI_MAINTENANCE_MODE_OFF:
- intf->maintenance_mode = mode;
- intf->maintenance_mode_enable = 0;
+ intf->maintenance_mode_enable = false;
break;
case IPMI_MAINTENANCE_MODE_ON:
- intf->maintenance_mode = mode;
- intf->maintenance_mode_enable = 1;
+ intf->maintenance_mode_enable = true;
break;
default:
rv = -EINVAL;
goto out_unlock;
}
+ intf->maintenance_mode = mode;
maintenance_mode_update(intf);
}
@@ -1184,7 +1211,7 @@ int ipmi_set_maintenance_mode(ipmi_user_t user, int mode)
}
EXPORT_SYMBOL(ipmi_set_maintenance_mode);
-int ipmi_set_gets_events(ipmi_user_t user, int val)
+int ipmi_set_gets_events(ipmi_user_t user, bool val)
{
unsigned long flags;
ipmi_smi_t intf = user->intf;
@@ -1194,8 +1221,18 @@ int ipmi_set_gets_events(ipmi_user_t user, int val)
INIT_LIST_HEAD(&msgs);
spin_lock_irqsave(&intf->events_lock, flags);
+ if (user->gets_events == val)
+ goto out;
+
user->gets_events = val;
+ if (val) {
+ if (atomic_inc_return(&intf->event_waiters) == 1)
+ need_waiter(intf);
+ } else {
+ atomic_dec(&intf->event_waiters);
+ }
+
if (intf->delivering_events)
/*
* Another thread is delivering events for this, so
@@ -1289,6 +1326,9 @@ int ipmi_register_for_cmd(ipmi_user_t user,
goto out_unlock;
}
+ if (atomic_inc_return(&intf->event_waiters) == 1)
+ need_waiter(intf);
+
list_add_rcu(&rcvr->link, &intf->cmd_rcvrs);
out_unlock:
@@ -1330,6 +1370,7 @@ int ipmi_unregister_for_cmd(ipmi_user_t user,
mutex_unlock(&intf->cmd_rcvrs_mutex);
synchronize_rcu();
while (rcvrs) {
+ atomic_dec(&intf->event_waiters);
rcvr = rcvrs;
rcvrs = rcvr->next;
kfree(rcvr);
@@ -1535,7 +1576,7 @@ static int i_ipmi_request(ipmi_user_t user,
= IPMI_MAINTENANCE_MODE_TIMEOUT;
if (!intf->maintenance_mode
&& !intf->maintenance_mode_enable) {
- intf->maintenance_mode_enable = 1;
+ intf->maintenance_mode_enable = true;
maintenance_mode_update(intf);
}
spin_unlock_irqrestore(&intf->maintenance_mode_lock,
@@ -2876,6 +2917,8 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
(unsigned long) intf);
atomic_set(&intf->watchdog_pretimeouts_to_deliver, 0);
spin_lock_init(&intf->events_lock);
+ atomic_set(&intf->event_waiters, 0);
+ intf->ticks_to_req_ev = IPMI_REQUEST_EV_TIME;
INIT_LIST_HEAD(&intf->waiting_events);
intf->waiting_events_count = 0;
mutex_init(&intf->cmd_rcvrs_mutex);
@@ -3965,7 +4008,8 @@ smi_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg,
static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent,
struct list_head *timeouts, long timeout_period,
- int slot, unsigned long *flags)
+ int slot, unsigned long *flags,
+ unsigned int *waiting_msgs)
{
struct ipmi_recv_msg *msg;
struct ipmi_smi_handlers *handlers;
@@ -3977,8 +4021,10 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent,
return;
ent->timeout -= timeout_period;
- if (ent->timeout > 0)
+ if (ent->timeout > 0) {
+ (*waiting_msgs)++;
return;
+ }
if (ent->retries_left == 0) {
/* The message has used all its retries. */
@@ -3995,6 +4041,8 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent,
struct ipmi_smi_msg *smi_msg;
/* More retries, send again. */
+ (*waiting_msgs)++;
+
/*
* Start with the max timer, set to normal timer after
* the message is sent.
@@ -4040,117 +4088,118 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent,
}
}
-static void ipmi_timeout_handler(long timeout_period)
+static unsigned int ipmi_timeout_handler(ipmi_smi_t intf, long timeout_period)
{
- ipmi_smi_t intf;
struct list_head timeouts;
struct ipmi_recv_msg *msg, *msg2;
unsigned long flags;
int i;
+ unsigned int waiting_msgs = 0;
- rcu_read_lock();
- list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
- tasklet_schedule(&intf->recv_tasklet);
-
- /*
- * Go through the seq table and find any messages that
- * have timed out, putting them in the timeouts
- * list.
- */
- INIT_LIST_HEAD(&timeouts);
- spin_lock_irqsave(&intf->seq_lock, flags);
- for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++)
- check_msg_timeout(intf, &(intf->seq_table[i]),
- &timeouts, timeout_period, i,
- &flags);
- spin_unlock_irqrestore(&intf->seq_lock, flags);
+ /*
+ * Go through the seq table and find any messages that
+ * have timed out, putting them in the timeouts
+ * list.
+ */
+ INIT_LIST_HEAD(&timeouts);
+ spin_lock_irqsave(&intf->seq_lock, flags);
+ for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++)
+ check_msg_timeout(intf, &(intf->seq_table[i]),
+ &timeouts, timeout_period, i,
+ &flags, &waiting_msgs);
+ spin_unlock_irqrestore(&intf->seq_lock, flags);
- list_for_each_entry_safe(msg, msg2, &timeouts, link)
- deliver_err_response(msg, IPMI_TIMEOUT_COMPLETION_CODE);
+ list_for_each_entry_safe(msg, msg2, &timeouts, link)
+ deliver_err_response(msg, IPMI_TIMEOUT_COMPLETION_CODE);
- /*
- * Maintenance mode handling. Check the timeout
- * optimistically before we claim the lock. It may
- * mean a timeout gets missed occasionally, but that
- * only means the timeout gets extended by one period
- * in that case. No big deal, and it avoids the lock
- * most of the time.
- */
+ /*
+ * Maintenance mode handling. Check the timeout
+ * optimistically before we claim the lock. It may
+ * mean a timeout gets missed occasionally, but that
+ * only means the timeout gets extended by one period
+ * in that case. No big deal, and it avoids the lock
+ * most of the time.
+ */
+ if (intf->auto_maintenance_timeout > 0) {
+ spin_lock_irqsave(&intf->maintenance_mode_lock, flags);
if (intf->auto_maintenance_timeout > 0) {
- spin_lock_irqsave(&intf->maintenance_mode_lock, flags);
- if (intf->auto_maintenance_timeout > 0) {
- intf->auto_maintenance_timeout
- -= timeout_period;
- if (!intf->maintenance_mode
- && (intf->auto_maintenance_timeout <= 0)) {
- intf->maintenance_mode_enable = 0;
- maintenance_mode_update(intf);
- }
+ intf->auto_maintenance_timeout
+ -= timeout_period;
+ if (!intf->maintenance_mode
+ && (intf->auto_maintenance_timeout <= 0)) {
+ intf->maintenance_mode_enable = false;
+ maintenance_mode_update(intf);
}
- spin_unlock_irqrestore(&intf->maintenance_mode_lock,
- flags);
}
+ spin_unlock_irqrestore(&intf->maintenance_mode_lock,
+ flags);
}
- rcu_read_unlock();
+
+ tasklet_schedule(&intf->recv_tasklet);
+
+ return waiting_msgs;
}
-static void ipmi_request_event(void)
+static void ipmi_request_event(ipmi_smi_t intf)
{
- ipmi_smi_t intf;
struct ipmi_smi_handlers *handlers;
- rcu_read_lock();
- /*
- * Called from the timer, no need to check if handlers is
- * valid.
- */
- list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
- /* No event requests when in maintenance mode. */
- if (intf->maintenance_mode_enable)
- continue;
+ /* No event requests when in maintenance mode. */
+ if (intf->maintenance_mode_enable)
+ return;
- handlers = intf->handlers;
- if (handlers)
- handlers->request_events(intf->send_info);
- }
- rcu_read_unlock();
+ handlers = intf->handlers;
+ if (handlers)
+ handlers->request_events(intf->send_info);
}
static struct timer_list ipmi_timer;
-/* Call every ~1000 ms. */
-#define IPMI_TIMEOUT_TIME 1000
-
-/* How many jiffies does it take to get to the timeout time. */
-#define IPMI_TIMEOUT_JIFFIES ((IPMI_TIMEOUT_TIME * HZ) / 1000)
-
-/*
- * Request events from the queue every second (this is the number of
- * IPMI_TIMEOUT_TIMES between event requests). Hopefully, in the
- * future, IPMI will add a way to know immediately if an event is in
- * the queue and this silliness can go away.
- */
-#define IPMI_REQUEST_EV_TIME (1000 / (IPMI_TIMEOUT_TIME))
-
static atomic_t stop_operation;
-static unsigned int ticks_to_req_ev = IPMI_REQUEST_EV_TIME;
static void ipmi_timeout(unsigned long data)
{
+ ipmi_smi_t intf;
+ int nt = 0;
+
if (atomic_read(&stop_operation))
return;
- ticks_to_req_ev--;
- if (ticks_to_req_ev == 0) {
- ipmi_request_event();
- ticks_to_req_ev = IPMI_REQUEST_EV_TIME;
- }
+ rcu_read_lock();
+ list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
+ int lnt = 0;
+
+ if (atomic_read(&intf->event_waiters)) {
+ intf->ticks_to_req_ev--;
+ if (intf->ticks_to_req_ev == 0) {
+ ipmi_request_event(intf);
+ intf->ticks_to_req_ev = IPMI_REQUEST_EV_TIME;
+ }
+ lnt++;
+ }
- ipmi_timeout_handler(IPMI_TIMEOUT_TIME);
+ lnt += ipmi_timeout_handler(intf, IPMI_TIMEOUT_TIME);
- mod_timer(&ipmi_timer, jiffies + IPMI_TIMEOUT_JIFFIES);
+ lnt = !!lnt;
+ if (lnt != intf->last_needs_timer &&
+ intf->handlers->set_need_watch)
+ intf->handlers->set_need_watch(intf->send_info, lnt);
+ intf->last_needs_timer = lnt;
+
+ nt += lnt;
+ }
+ rcu_read_unlock();
+
+ if (nt)
+ mod_timer(&ipmi_timer, jiffies + IPMI_TIMEOUT_JIFFIES);
}
+static void need_waiter(ipmi_smi_t intf)
+{
+ /* Racy, but worst case we start the timer twice. */
+ if (!timer_pending(&ipmi_timer))
+ mod_timer(&ipmi_timer, jiffies + IPMI_TIMEOUT_JIFFIES);
+}
static atomic_t smi_msg_inuse_count = ATOMIC_INIT(0);
static atomic_t recv_msg_inuse_count = ATOMIC_INIT(0);
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index b7efd3c1a882..1c4bb4f6ce93 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -217,7 +217,7 @@ struct smi_info {
unsigned char msg_flags;
/* Does the BMC have an event buffer? */
- char has_event_buffer;
+ bool has_event_buffer;
/*
* If set to true, this will request events the next time the
@@ -230,7 +230,7 @@ struct smi_info {
* call. Generally used after a panic to make sure stuff goes
* out.
*/
- int run_to_completion;
+ bool run_to_completion;
/* The I/O port of an SI interface. */
int port;
@@ -248,19 +248,25 @@ struct smi_info {
/* The timer for this si. */
struct timer_list si_timer;
+ /* This flag is set, if the timer is running (timer_pending() isn't enough) */
+ bool timer_running;
+
/* The time (in jiffies) the last timeout occurred at. */
unsigned long last_timeout_jiffies;
/* Used to gracefully stop the timer without race conditions. */
atomic_t stop_operation;
+ /* Are we waiting for the events, pretimeouts, received msgs? */
+ atomic_t need_watch;
+
/*
* The driver will disable interrupts when it gets into a
* situation where it cannot handle messages due to lack of
* memory. Once that situation clears up, it will re-enable
* interrupts.
*/
- int interrupt_disabled;
+ bool interrupt_disabled;
/* From the get device id response... */
struct ipmi_device_id device_id;
@@ -273,7 +279,7 @@ struct smi_info {
* True if we allocated the device, false if it came from
* someplace else (like PCI).
*/
- int dev_registered;
+ bool dev_registered;
/* Slave address, could be reported from DMI. */
unsigned char slave_addr;
@@ -297,19 +303,19 @@ struct smi_info {
static int force_kipmid[SI_MAX_PARMS];
static int num_force_kipmid;
#ifdef CONFIG_PCI
-static int pci_registered;
+static bool pci_registered;
#endif
#ifdef CONFIG_ACPI
-static int pnp_registered;
+static bool pnp_registered;
#endif
#ifdef CONFIG_PARISC
-static int parisc_registered;
+static bool parisc_registered;
#endif
static unsigned int kipmid_max_busy_us[SI_MAX_PARMS];
static int num_max_busy_us;
-static int unload_when_empty = 1;
+static bool unload_when_empty = true;
static int add_smi(struct smi_info *smi);
static int try_smi_init(struct smi_info *smi);
@@ -434,6 +440,13 @@ static void start_clear_flags(struct smi_info *smi_info)
smi_info->si_state = SI_CLEARING_FLAGS;
}
+static void smi_mod_timer(struct smi_info *smi_info, unsigned long new_val)
+{
+ smi_info->last_timeout_jiffies = jiffies;
+ mod_timer(&smi_info->si_timer, new_val);
+ smi_info->timer_running = true;
+}
+
/*
* When we have a situtaion where we run out of memory and cannot
* allocate messages, we just leave them in the BMC and run the system
@@ -444,10 +457,9 @@ static inline void disable_si_irq(struct smi_info *smi_info)
{
if ((smi_info->irq) && (!smi_info->interrupt_disabled)) {
start_disable_irq(smi_info);
- smi_info->interrupt_disabled = 1;
+ smi_info->interrupt_disabled = true;
if (!atomic_read(&smi_info->stop_operation))
- mod_timer(&smi_info->si_timer,
- jiffies + SI_TIMEOUT_JIFFIES);
+ smi_mod_timer(smi_info, jiffies + SI_TIMEOUT_JIFFIES);
}
}
@@ -455,7 +467,7 @@ static inline void enable_si_irq(struct smi_info *smi_info)
{
if ((smi_info->irq) && (smi_info->interrupt_disabled)) {
start_enable_irq(smi_info);
- smi_info->interrupt_disabled = 0;
+ smi_info->interrupt_disabled = false;
}
}
@@ -700,7 +712,7 @@ static void handle_transaction_done(struct smi_info *smi_info)
dev_warn(smi_info->dev,
"Maybe ok, but ipmi might run very slowly.\n");
} else
- smi_info->interrupt_disabled = 0;
+ smi_info->interrupt_disabled = false;
smi_info->si_state = SI_NORMAL;
break;
}
@@ -853,6 +865,19 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info,
return si_sm_result;
}
+static void check_start_timer_thread(struct smi_info *smi_info)
+{
+ if (smi_info->si_state == SI_NORMAL && smi_info->curr_msg == NULL) {
+ smi_mod_timer(smi_info, jiffies + SI_TIMEOUT_JIFFIES);
+
+ if (smi_info->thread)
+ wake_up_process(smi_info->thread);
+
+ start_next_msg(smi_info);
+ smi_event_handler(smi_info, 0);
+ }
+}
+
static void sender(void *send_info,
struct ipmi_smi_msg *msg,
int priority)
@@ -906,27 +931,11 @@ static void sender(void *send_info,
else
list_add_tail(&msg->link, &smi_info->xmit_msgs);
- if (smi_info->si_state == SI_NORMAL && smi_info->curr_msg == NULL) {
- /*
- * last_timeout_jiffies is updated here to avoid
- * smi_timeout() handler passing very large time_diff
- * value to smi_event_handler() that causes
- * the send command to abort.
- */
- smi_info->last_timeout_jiffies = jiffies;
-
- mod_timer(&smi_info->si_timer, jiffies + SI_TIMEOUT_JIFFIES);
-
- if (smi_info->thread)
- wake_up_process(smi_info->thread);
-
- start_next_msg(smi_info);
- smi_event_handler(smi_info, 0);
- }
+ check_start_timer_thread(smi_info);
spin_unlock_irqrestore(&smi_info->si_lock, flags);
}
-static void set_run_to_completion(void *send_info, int i_run_to_completion)
+static void set_run_to_completion(void *send_info, bool i_run_to_completion)
{
struct smi_info *smi_info = send_info;
enum si_sm_result result;
@@ -1004,6 +1013,17 @@ static int ipmi_thread(void *data)
spin_lock_irqsave(&(smi_info->si_lock), flags);
smi_result = smi_event_handler(smi_info, 0);
+
+ /*
+ * If the driver is doing something, there is a possible
+ * race with the timer. If the timer handler see idle,
+ * and the thread here sees something else, the timer
+ * handler won't restart the timer even though it is
+ * required. So start it here if necessary.
+ */
+ if (smi_result != SI_SM_IDLE && !smi_info->timer_running)
+ smi_mod_timer(smi_info, jiffies + SI_TIMEOUT_JIFFIES);
+
spin_unlock_irqrestore(&(smi_info->si_lock), flags);
busy_wait = ipmi_thread_busy_wait(smi_result, smi_info,
&busy_until);
@@ -1011,9 +1031,15 @@ static int ipmi_thread(void *data)
; /* do nothing */
else if (smi_result == SI_SM_CALL_WITH_DELAY && busy_wait)
schedule();
- else if (smi_result == SI_SM_IDLE)
- schedule_timeout_interruptible(100);
- else
+ else if (smi_result == SI_SM_IDLE) {
+ if (atomic_read(&smi_info->need_watch)) {
+ schedule_timeout_interruptible(100);
+ } else {
+ /* Wait to be woken up when we are needed. */
+ __set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ }
+ } else
schedule_timeout_interruptible(1);
}
return 0;
@@ -1024,7 +1050,7 @@ static void poll(void *send_info)
{
struct smi_info *smi_info = send_info;
unsigned long flags = 0;
- int run_to_completion = smi_info->run_to_completion;
+ bool run_to_completion = smi_info->run_to_completion;
/*
* Make sure there is some delay in the poll loop so we can
@@ -1049,6 +1075,17 @@ static void request_events(void *send_info)
atomic_set(&smi_info->req_events, 1);
}
+static void set_need_watch(void *send_info, bool enable)
+{
+ struct smi_info *smi_info = send_info;
+ unsigned long flags;
+
+ atomic_set(&smi_info->need_watch, enable);
+ spin_lock_irqsave(&smi_info->si_lock, flags);
+ check_start_timer_thread(smi_info);
+ spin_unlock_irqrestore(&smi_info->si_lock, flags);
+}
+
static int initialized;
static void smi_timeout(unsigned long data)
@@ -1073,10 +1110,6 @@ static void smi_timeout(unsigned long data)
* SI_USEC_PER_JIFFY);
smi_result = smi_event_handler(smi_info, time_diff);
- spin_unlock_irqrestore(&(smi_info->si_lock), flags);
-
- smi_info->last_timeout_jiffies = jiffies_now;
-
if ((smi_info->irq) && (!smi_info->interrupt_disabled)) {
/* Running with interrupts, only do long timeouts. */
timeout = jiffies + SI_TIMEOUT_JIFFIES;
@@ -1098,7 +1131,10 @@ static void smi_timeout(unsigned long data)
do_mod_timer:
if (smi_result != SI_SM_IDLE)
- mod_timer(&(smi_info->si_timer), timeout);
+ smi_mod_timer(smi_info, timeout);
+ else
+ smi_info->timer_running = false;
+ spin_unlock_irqrestore(&(smi_info->si_lock), flags);
}
static irqreturn_t si_irq_handler(int irq, void *data)
@@ -1146,8 +1182,7 @@ static int smi_start_processing(void *send_info,
/* Set up the timer that drives the interface. */
setup_timer(&new_smi->si_timer, smi_timeout, (long)new_smi);
- new_smi->last_timeout_jiffies = jiffies;
- mod_timer(&new_smi->si_timer, jiffies + SI_TIMEOUT_JIFFIES);
+ smi_mod_timer(new_smi, jiffies + SI_TIMEOUT_JIFFIES);
/*
* Check if the user forcefully enabled the daemon.
@@ -1188,7 +1223,7 @@ static int get_smi_info(void *send_info, struct ipmi_smi_info *data)
return 0;
}
-static void set_maintenance_mode(void *send_info, int enable)
+static void set_maintenance_mode(void *send_info, bool enable)
{
struct smi_info *smi_info = send_info;
@@ -1202,6 +1237,7 @@ static struct ipmi_smi_handlers handlers = {
.get_smi_info = get_smi_info,
.sender = sender,
.request_events = request_events,
+ .set_need_watch = set_need_watch,
.set_maintenance_mode = set_maintenance_mode,
.set_run_to_completion = set_run_to_completion,
.poll = poll,
@@ -1229,7 +1265,7 @@ static bool si_tryplatform = 1;
#ifdef CONFIG_PCI
static bool si_trypci = 1;
#endif
-static bool si_trydefaults = 1;
+static bool si_trydefaults = IS_ENABLED(CONFIG_IPMI_SI_PROBE_DEFAULTS);
static char *si_type[SI_MAX_PARMS];
#define MAX_SI_TYPE_STR 30
static char si_type_str[MAX_SI_TYPE_STR];
@@ -1328,7 +1364,7 @@ module_param_array(force_kipmid, int, &num_force_kipmid, 0);
MODULE_PARM_DESC(force_kipmid, "Force the kipmi daemon to be enabled (1) or"
" disabled(0). Normally the IPMI driver auto-detects"
" this, but the value may be overridden by this parm.");
-module_param(unload_when_empty, int, 0);
+module_param(unload_when_empty, bool, 0);
MODULE_PARM_DESC(unload_when_empty, "Unload the module if no interfaces are"
" specified or found, default is 1. Setting to 0"
" is useful for hot add of devices using hotmod.");
@@ -3336,18 +3372,19 @@ static int try_smi_init(struct smi_info *new_smi)
INIT_LIST_HEAD(&(new_smi->hp_xmit_msgs));
new_smi->curr_msg = NULL;
atomic_set(&new_smi->req_events, 0);
- new_smi->run_to_completion = 0;
+ new_smi->run_to_completion = false;
for (i = 0; i < SI_NUM_STATS; i++)
atomic_set(&new_smi->stats[i], 0);
- new_smi->interrupt_disabled = 1;
+ new_smi->interrupt_disabled = true;
atomic_set(&new_smi->stop_operation, 0);
+ atomic_set(&new_smi->need_watch, 0);
new_smi->intf_num = smi_num;
smi_num++;
rv = try_enable_event_buffer(new_smi);
if (rv == 0)
- new_smi->has_event_buffer = 1;
+ new_smi->has_event_buffer = true;
/*
* Start clearing the flags before we enable interrupts or the
@@ -3381,7 +3418,7 @@ static int try_smi_init(struct smi_info *new_smi)
rv);
goto out_err;
}
- new_smi->dev_registered = 1;
+ new_smi->dev_registered = true;
}
rv = ipmi_register_smi(&handlers,
@@ -3430,7 +3467,7 @@ static int try_smi_init(struct smi_info *new_smi)
wait_for_timer_and_thread(new_smi);
out_err:
- new_smi->interrupt_disabled = 1;
+ new_smi->interrupt_disabled = true;
if (new_smi->intf) {
ipmi_unregister_smi(new_smi->intf);
@@ -3466,7 +3503,7 @@ static int try_smi_init(struct smi_info *new_smi)
if (new_smi->dev_registered) {
platform_device_unregister(new_smi->pdev);
- new_smi->dev_registered = 0;
+ new_smi->dev_registered = false;
}
return rv;
@@ -3521,14 +3558,14 @@ static int init_ipmi_si(void)
printk(KERN_ERR PFX "Unable to register "
"PCI driver: %d\n", rv);
else
- pci_registered = 1;
+ pci_registered = true;
}
#endif
#ifdef CONFIG_ACPI
if (si_tryacpi) {
pnp_register_driver(&ipmi_pnp_driver);
- pnp_registered = 1;
+ pnp_registered = true;
}
#endif
@@ -3544,7 +3581,7 @@ static int init_ipmi_si(void)
#ifdef CONFIG_PARISC
register_parisc_driver(&ipmi_parisc_driver);
- parisc_registered = 1;
+ parisc_registered = true;
/* poking PC IO addresses will crash machine, don't do it */
si_trydefaults = 0;
#endif
diff --git a/drivers/char/pcmcia/Kconfig b/drivers/char/pcmcia/Kconfig
index b27f5342fe76..8d3dfb0c8a26 100644
--- a/drivers/char/pcmcia/Kconfig
+++ b/drivers/char/pcmcia/Kconfig
@@ -15,7 +15,7 @@ config SYNCLINK_CS
This driver may be built as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
- The module will be called synclinkmp. If you want to do that, say M
+ The module will be called synclink_cs. If you want to do that, say M
here.
config CARDMAN_4000
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 0a19d866a153..06cea7ff3a7c 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -996,8 +996,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;
diff --git a/drivers/char/tpm/tpm_ppi.c b/drivers/char/tpm/tpm_ppi.c
index b3ea223585bd..61dcc8011ec7 100644
--- a/drivers/char/tpm/tpm_ppi.c
+++ b/drivers/char/tpm/tpm_ppi.c
@@ -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);
}
diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c
index daea84c41743..a15ce4ef39cd 100644
--- a/drivers/char/ttyprintk.c
+++ b/drivers/char/ttyprintk.c
@@ -17,7 +17,7 @@
#include <linux/device.h>
#include <linux/serial.h>
#include <linux/tty.h>
-#include <linux/export.h>
+#include <linux/module.h>
struct ttyprintk_port {
struct tty_port port;
@@ -210,10 +210,19 @@ static int __init ttyprintk_init(void)
return 0;
error:
- tty_unregister_driver(ttyprintk_driver);
put_tty_driver(ttyprintk_driver);
tty_port_destroy(&tpk_port.port);
- ttyprintk_driver = NULL;
return ret;
}
+
+static void __exit ttyprintk_exit(void)
+{
+ tty_unregister_driver(ttyprintk_driver);
+ put_tty_driver(ttyprintk_driver);
+ tty_port_destroy(&tpk_port.port);
+}
+
device_initcall(ttyprintk_init);
+module_exit(ttyprintk_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/bcm/clk-kona-setup.c b/drivers/clk/bcm/clk-kona-setup.c
index c7607feb18dd..54a06526f64f 100644
--- a/drivers/clk/bcm/clk-kona-setup.c
+++ b/drivers/clk/bcm/clk-kona-setup.c
@@ -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)) {
diff --git a/drivers/clk/bcm/clk-kona.c b/drivers/clk/bcm/clk-kona.c
index e3d339e08309..db11a87449f2 100644
--- a/drivers/clk/bcm/clk-kona.c
+++ b/drivers/clk/bcm/clk-kona.c
@@ -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;
diff --git a/drivers/clk/bcm/clk-kona.h b/drivers/clk/bcm/clk-kona.h
index 5e139adc3dc5..dee690951bb6 100644
--- a/drivers/clk/bcm/clk-kona.h
+++ b/drivers/clk/bcm/clk-kona.h
@@ -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)
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index ec22112e569f..3fbee4540228 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -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))
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index dff0373f53c1..7cf2c093cc54 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -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;
diff --git a/drivers/clk/shmobile/clk-mstp.c b/drivers/clk/shmobile/clk-mstp.c
index 2e5810c88d11..1f6324e29a80 100644
--- a/drivers/clk/shmobile/clk-mstp.c
+++ b/drivers/clk/shmobile/clk-mstp.c
@@ -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;
diff --git a/drivers/clk/socfpga/clk-pll.c b/drivers/clk/socfpga/clk-pll.c
index 88dafb5e9627..de6da957a09d 100644
--- a/drivers/clk/socfpga/clk-pll.c
+++ b/drivers/clk/socfpga/clk-pll.c
@@ -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);
diff --git a/drivers/clk/socfpga/clk.c b/drivers/clk/socfpga/clk.c
index 35a960a993f9..43db947e5f0e 100644
--- a/drivers/clk/socfpga/clk.c
+++ b/drivers/clk/socfpga/clk.c
@@ -17,28 +17,11 @@
* 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);
diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c
index bca0a0badbfa..a886702f7c8b 100644
--- a/drivers/clk/st/clkgen-pll.c
+++ b/drivers/clk/st/clkgen-pll.c
@@ -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;
diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
index 0d20241e0770..6aad8abc69a2 100644
--- a/drivers/clk/tegra/clk-pll.c
+++ b/drivers/clk/tegra/clk-pll.c
@@ -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
@@ -183,6 +183,14 @@
#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,
diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c
index 166e02f16c8a..cc37c342c4cb 100644
--- a/drivers/clk/tegra/clk-tegra124.c
+++ b/drivers/clk/tegra/clk-tegra124.c
@@ -764,7 +764,6 @@ static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = {
[tegra_clk_sdmmc2_8] = { .dt_id = TEGRA124_CLK_SDMMC2, .present = true },
[tegra_clk_i2s1] = { .dt_id = TEGRA124_CLK_I2S1, .present = true },
[tegra_clk_i2c1] = { .dt_id = TEGRA124_CLK_I2C1, .present = true },
- [tegra_clk_ndflash] = { .dt_id = TEGRA124_CLK_NDFLASH, .present = true },
[tegra_clk_sdmmc1_8] = { .dt_id = TEGRA124_CLK_SDMMC1, .present = true },
[tegra_clk_sdmmc4_8] = { .dt_id = TEGRA124_CLK_SDMMC4, .present = true },
[tegra_clk_pwm] = { .dt_id = TEGRA124_CLK_PWM, .present = true },
@@ -809,7 +808,6 @@ static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = {
[tegra_clk_trace] = { .dt_id = TEGRA124_CLK_TRACE, .present = true },
[tegra_clk_soc_therm] = { .dt_id = TEGRA124_CLK_SOC_THERM, .present = true },
[tegra_clk_dtv] = { .dt_id = TEGRA124_CLK_DTV, .present = true },
- [tegra_clk_ndspeed] = { .dt_id = TEGRA124_CLK_NDSPEED, .present = true },
[tegra_clk_i2cslow] = { .dt_id = TEGRA124_CLK_I2CSLOW, .present = true },
[tegra_clk_dsib] = { .dt_id = TEGRA124_CLK_DSIB, .present = true },
[tegra_clk_tsec] = { .dt_id = TEGRA124_CLK_TSEC, .present = true },
@@ -952,7 +950,6 @@ static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = {
[tegra_clk_clk_out_3_mux] = { .dt_id = TEGRA124_CLK_CLK_OUT_3_MUX, .present = true },
[tegra_clk_dsia_mux] = { .dt_id = TEGRA124_CLK_DSIA_MUX, .present = true },
[tegra_clk_dsib_mux] = { .dt_id = TEGRA124_CLK_DSIB_MUX, .present = true },
- [tegra_clk_uarte] = { .dt_id = TEGRA124_CLK_UARTE, .present = true },
};
static struct tegra_devclk devclks[] __initdata = {
diff --git a/drivers/clk/versatile/clk-vexpress-osc.c b/drivers/clk/versatile/clk-vexpress-osc.c
index 2dc8b41a339d..422391242b39 100644
--- a/drivers/clk/versatile/clk-vexpress-osc.c
+++ b/drivers/clk/versatile/clk-vexpress-osc.c
@@ -100,9 +100,11 @@ 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)
- goto error;
+ return;
osc->func = vexpress_config_func_get_by_node(node);
if (!osc->func) {
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 57e823c44d2a..5163ec13429d 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -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();
}
diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c
index a6ee6d7cd63f..acf5a329d538 100644
--- a/drivers/clocksource/exynos_mct.c
+++ b/drivers/clocksource/exynos_mct.c
@@ -416,8 +416,6 @@ static int exynos4_local_timer_setup(struct clock_event_device *evt)
evt->set_mode = exynos4_tick_set_mode;
evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
evt->rating = 450;
- clockevents_config_and_register(evt, clk_rate / (TICK_BASE_CNT + 1),
- 0xf, 0x7fffffff);
exynos4_mct_write(TICK_BASE_CNT, mevt->base + MCT_L_TCNTB_OFFSET);
@@ -430,9 +428,12 @@ static int exynos4_local_timer_setup(struct clock_event_device *evt)
evt->irq);
return -EIO;
}
+ irq_force_affinity(mct_irqs[MCT_L0_IRQ + cpu], cpumask_of(cpu));
} else {
enable_percpu_irq(mct_irqs[MCT_L0_IRQ], 0);
}
+ clockevents_config_and_register(evt, clk_rate / (TICK_BASE_CNT + 1),
+ 0xf, 0x7fffffff);
return 0;
}
@@ -450,7 +451,6 @@ static int exynos4_mct_cpu_notify(struct notifier_block *self,
unsigned long action, void *hcpu)
{
struct mct_clock_event_device *mevt;
- unsigned int cpu;
/*
* Grab cpu pointer in each case to avoid spurious
@@ -461,12 +461,6 @@ static int exynos4_mct_cpu_notify(struct notifier_block *self,
mevt = this_cpu_ptr(&percpu_mct_tick);
exynos4_local_timer_setup(&mevt->evt);
break;
- case CPU_ONLINE:
- cpu = (unsigned long)hcpu;
- if (mct_int_type == MCT_INT_SPI)
- irq_set_affinity(mct_irqs[MCT_L0_IRQ + cpu],
- cpumask_of(cpu));
- break;
case CPU_DYING:
mevt = this_cpu_ptr(&percpu_mct_tick);
exynos4_local_timer_stop(&mevt->evt);
diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c
index 00fdd1170284..a8d7ea14f183 100644
--- a/drivers/clocksource/tcb_clksrc.c
+++ b/drivers/clocksource/tcb_clksrc.c
@@ -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;
diff --git a/drivers/clocksource/timer-marco.c b/drivers/clocksource/timer-marco.c
index b52e1c078b99..7f5374dbefd9 100644
--- a/drivers/clocksource/timer-marco.c
+++ b/drivers/clocksource/timer-marco.c
@@ -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;
diff --git a/drivers/clocksource/zevio-timer.c b/drivers/clocksource/zevio-timer.c
index ca81809d159d..7ce442148c3f 100644
--- a/drivers/clocksource/zevio-timer.c
+++ b/drivers/clocksource/zevio-timer.c
@@ -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);
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
index 148d707a1d43..ccdd4c7e748b 100644
--- a/drivers/connector/cn_proc.c
+++ b/drivers/connector/cn_proc.c
@@ -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;
}
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 0e9cce82844b..580503513f0f 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -92,11 +92,7 @@ config ARM_EXYNOS_CPU_FREQ_BOOST_SW
config ARM_HIGHBANK_CPUFREQ
tristate "Calxeda Highbank-based"
- depends on ARCH_HIGHBANK
- select GENERIC_CPUFREQ_CPU0
- select PM_OPP
- select REGULATOR
-
+ depends on ARCH_HIGHBANK && GENERIC_CPUFREQ_CPU0 && REGULATOR
default m
help
This adds the CPUFreq driver for Calxeda Highbank SoC
diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
index 1bf6bbac3e03..09b9129c7bd3 100644
--- a/drivers/cpufreq/cpufreq-cpu0.c
+++ b/drivers/cpufreq/cpufreq-cpu0.c
@@ -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;
diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c
index ba43991ba98a..e1c6433b16e0 100644
--- a/drivers/cpufreq/cpufreq_governor.c
+++ b/drivers/cpufreq/cpufreq_governor.c
@@ -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;
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 099967302bf2..eab8ccfe6beb 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -37,6 +37,7 @@
#define BYT_RATIOS 0x66a
#define BYT_VIDS 0x66b
#define BYT_TURBO_RATIOS 0x66c
+#define BYT_TURBO_VIDS 0x66d
#define FRAC_BITS 6
@@ -70,8 +71,9 @@ struct pstate_data {
};
struct vid_data {
- int32_t min;
- int32_t max;
+ int min;
+ int max;
+ int turbo;
int32_t ratio;
};
@@ -359,14 +361,14 @@ static int byt_get_min_pstate(void)
{
u64 value;
rdmsrl(BYT_RATIOS, value);
- return (value >> 8) & 0xFF;
+ return (value >> 8) & 0x3F;
}
static int byt_get_max_pstate(void)
{
u64 value;
rdmsrl(BYT_RATIOS, value);
- return (value >> 16) & 0xFF;
+ return (value >> 16) & 0x3F;
}
static int byt_get_turbo_pstate(void)
@@ -393,6 +395,9 @@ static void byt_set_pstate(struct cpudata *cpudata, int pstate)
vid_fp = clamp_t(int32_t, vid_fp, cpudata->vid.min, cpudata->vid.max);
vid = fp_toint(vid_fp);
+ if (pstate > cpudata->pstate.max_pstate)
+ vid = cpudata->vid.turbo;
+
val |= vid;
wrmsrl(MSR_IA32_PERF_CTL, val);
@@ -402,13 +407,17 @@ static void byt_get_vid(struct cpudata *cpudata)
{
u64 value;
+
rdmsrl(BYT_VIDS, value);
- cpudata->vid.min = int_tofp((value >> 8) & 0x7f);
- cpudata->vid.max = int_tofp((value >> 16) & 0x7f);
+ cpudata->vid.min = int_tofp((value >> 8) & 0x3f);
+ cpudata->vid.max = int_tofp((value >> 16) & 0x3f);
cpudata->vid.ratio = div_fp(
cpudata->vid.max - cpudata->vid.min,
int_tofp(cpudata->pstate.max_pstate -
cpudata->pstate.min_pstate));
+
+ rdmsrl(BYT_TURBO_VIDS, value);
+ cpudata->vid.turbo = value & 0x7f;
}
@@ -545,12 +554,7 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
if (pstate_funcs.get_vid)
pstate_funcs.get_vid(cpu);
-
- /*
- * goto max pstate so we don't slow up boot if we are built-in if we are
- * a module we will take care of it during normal operation
- */
- intel_pstate_set_pstate(cpu, cpu->pstate.max_pstate);
+ intel_pstate_set_pstate(cpu, cpu->pstate.min_pstate);
}
static inline void intel_pstate_calc_busy(struct cpudata *cpu,
@@ -695,11 +699,6 @@ static int intel_pstate_init_cpu(unsigned int cpunum)
cpu = all_cpu_data[cpunum];
intel_pstate_get_cpu_pstates(cpu);
- if (!cpu->pstate.current_pstate) {
- all_cpu_data[cpunum] = NULL;
- kfree(cpu);
- return -ENODATA;
- }
cpu->cpu = cpunum;
@@ -710,7 +709,6 @@ static int intel_pstate_init_cpu(unsigned int cpunum)
cpu->timer.expires = jiffies + HZ/100;
intel_pstate_busy_pid_reset(cpu);
intel_pstate_sample(cpu);
- intel_pstate_set_pstate(cpu, cpu->pstate.max_pstate);
add_timer_on(&cpu->timer, cpunum);
diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c
index d00e5d1abd25..5c4369b5d834 100644
--- a/drivers/cpufreq/longhaul.c
+++ b/drivers/cpufreq/longhaul.c
@@ -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;
}
}
diff --git a/drivers/cpufreq/loongson2_cpufreq.c b/drivers/cpufreq/loongson2_cpufreq.c
index f0bc31f5db27..d4add8621944 100644
--- a/drivers/cpufreq/loongson2_cpufreq.c
+++ b/drivers/cpufreq/loongson2_cpufreq.c
@@ -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;
diff --git a/drivers/cpufreq/powernow-k6.c b/drivers/cpufreq/powernow-k6.c
index 49f120e1bc7b..78904e6ca4a0 100644
--- a/drivers/cpufreq/powernow-k6.c
+++ b/drivers/cpufreq/powernow-k6.c
@@ -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;
}
diff --git a/drivers/cpufreq/powernow-k7.c b/drivers/cpufreq/powernow-k7.c
index f911645c3f6d..e61e224475ad 100644
--- a/drivers/cpufreq/powernow-k7.c
+++ b/drivers/cpufreq/powernow-k7.c
@@ -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;
}
diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c
index 9edccc63245d..af4968813e76 100644
--- a/drivers/cpufreq/powernv-cpufreq.c
+++ b/drivers/cpufreq/powernv-cpufreq.c
@@ -29,6 +29,7 @@
#include <asm/cputhreads.h>
#include <asm/reg.h>
+#include <asm/smp.h> /* Required for cpu_sibling_mask() in UP configs */
#define POWERNV_MAX_PSTATES 256
diff --git a/drivers/cpufreq/ppc-corenet-cpufreq.c b/drivers/cpufreq/ppc-corenet-cpufreq.c
index b7e677be1df0..0af618abebaf 100644
--- a/drivers/cpufreq/ppc-corenet-cpufreq.c
+++ b/drivers/cpufreq/ppc-corenet-cpufreq.c
@@ -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 =
- (12 * NSEC_PER_SEC) / fsl_get_sys_freq();
+ do_div(transition_latency_hz, fsl_get_sys_freq());
+
of_node_put(np);
return 0;
diff --git a/drivers/cpufreq/unicore2-cpufreq.c b/drivers/cpufreq/unicore2-cpufreq.c
index 8d045afa7fb4..6f9dfa80563a 100644
--- a/drivers/cpufreq/unicore2-cpufreq.c
+++ b/drivers/cpufreq/unicore2-cpufreq.c
@@ -60,9 +60,7 @@ static int __init ucv2_cpu_init(struct cpufreq_policy *policy)
policy->max = policy->cpuinfo.max_freq = 1000000;
policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
policy->clk = clk_get(NULL, "MAIN_CLK");
- if (IS_ERR(policy->clk))
- return PTR_ERR(policy->clk);
- return 0;
+ return PTR_ERR_OR_ZERO(policy->clk);
}
static struct cpufreq_driver ucv2_driver = {
diff --git a/drivers/crypto/caam/error.c b/drivers/crypto/caam/error.c
index 9f25f5296029..0eabd81e1a90 100644
--- a/drivers/crypto/caam/error.c
+++ b/drivers/crypto/caam/error.c
@@ -16,9 +16,13 @@
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)
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index ba06d1d2f99e..5c5863842de9 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -197,7 +197,7 @@ config AMCC_PPC440SPE_ADMA
config TIMB_DMA
tristate "Timberdale FPGA DMA support"
- depends on MFD_TIMBERDALE || HAS_IOMEM
+ depends on MFD_TIMBERDALE
select DMA_ENGINE
help
Enable support for the Timberdale FPGA DMA engine.
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index a886713937fd..d5d30ed863ce 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -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;
}
diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c
index cfdbb92aae1d..7a740769c2fa 100644
--- a/drivers/dma/dw/core.c
+++ b/drivers/dma/dw/core.c
@@ -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,
diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
index cd04eb7b182e..926360c2db6a 100644
--- a/drivers/dma/edma.c
+++ b/drivers/dma/edma.c
@@ -182,11 +182,13 @@ static void edma_execute(struct edma_chan *echan)
echan->ecc->dummy_slot);
}
- edma_resume(echan->ch_num);
-
if (edesc->processed <= MAX_NR_SG) {
dev_dbg(dev, "first transfer starting %d\n", echan->ch_num);
edma_start(echan->ch_num);
+ } else {
+ dev_dbg(dev, "chan: %d: completed %d elements, resuming\n",
+ echan->ch_num, edesc->processed);
+ edma_resume(echan->ch_num);
}
/*
diff --git a/drivers/dma/fsl-edma.c b/drivers/dma/fsl-edma.c
index 381e793184ba..b396a7fb53ab 100644
--- a/drivers/dma/fsl-edma.c
+++ b/drivers/dma/fsl-edma.c
@@ -968,7 +968,17 @@ static struct platform_driver fsl_edma_driver = {
.remove = fsl_edma_remove,
};
-module_platform_driver(fsl_edma_driver);
+static int __init fsl_edma_init(void)
+{
+ return platform_driver_register(&fsl_edma_driver);
+}
+subsys_initcall(fsl_edma_init);
+
+static void __exit fsl_edma_exit(void)
+{
+ platform_driver_unregister(&fsl_edma_driver);
+}
+module_exit(fsl_edma_exit);
MODULE_ALIAS("platform:fsl-edma");
MODULE_DESCRIPTION("Freescale eDMA engine driver");
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index 766b68ed505c..394cbc5c93e3 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -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)
diff --git a/drivers/dma/sa11x0-dma.c b/drivers/dma/sa11x0-dma.c
index ab26d46bbe15..5ebdfbc1051e 100644
--- a/drivers/dma/sa11x0-dma.c
+++ b/drivers/dma/sa11x0-dma.c
@@ -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,
diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c
index a1bd8298d55f..03f7820fa333 100644
--- a/drivers/dma/sirf-dma.c
+++ b/drivers/dma/sirf-dma.c
@@ -666,7 +666,7 @@ static struct dma_chan *of_dma_sirfsoc_xlate(struct of_phandle_args *dma_spec,
struct sirfsoc_dma *sdma = ofdma->of_dma_data;
unsigned int request = dma_spec->args[0];
- if (request > SIRFSOC_DMA_CHANNELS)
+ if (request >= SIRFSOC_DMA_CHANNELS)
return NULL;
return dma_get_slave_channel(&sdma->channels[request].chan);
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 33edd6766344..2c694b5297cc 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -1018,7 +1018,7 @@ static void edac_ce_error(struct mem_ctl_info *mci,
}
edac_inc_ce_error(mci, enable_per_layer_report, pos, error_count);
- if (mci->scrub_mode & SCRUB_SW_SRC) {
+ if (mci->scrub_mode == SCRUB_SW_SRC) {
/*
* Some memory controllers (called MCs below) can remap
* memory so that it is still available at a different
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
index 51b9caa0b024..5f43620d580a 100644
--- a/drivers/edac/mce_amd.c
+++ b/drivers/edac/mce_amd.c
@@ -6,7 +6,6 @@
static struct amd_decoder_ops *fam_ops;
static u8 xec_mask = 0xf;
-static u8 nb_err_cpumask = 0xf;
static bool report_gart_errors;
static void (*nb_bus_decoder)(int node_id, struct mce *m);
@@ -852,7 +851,6 @@ static int __init mce_amd_init(void)
break;
case 0x14:
- nb_err_cpumask = 0x3;
fam_ops->mc0_mce = cat_mc0_mce;
fam_ops->mc1_mce = cat_mc1_mce;
fam_ops->mc2_mce = k8_mc2_mce;
diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h
index c98764aeeec6..f477308b6e9c 100644
--- a/drivers/firewire/core.h
+++ b/drivers/firewire/core.h
@@ -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);
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 8db663219560..586f2f7f6993 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -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;
diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c
index 3ee852c9925b..071c2c969eec 100644
--- a/drivers/firmware/iscsi_ibft.c
+++ b/drivers/firmware/iscsi_ibft.c
@@ -756,6 +756,7 @@ static const struct {
*/
{ ACPI_SIG_IBFT },
{ "iBFT" },
+ { "BIFT" }, /* Broadcom iSCSI Offload */
};
static void __init acpi_find_ibft_region(void)
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index a86c49a605c6..4a1b5113e527 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -56,6 +56,7 @@ config GPIO_ACPI
depends on ACPI
config GPIOLIB_IRQCHIP
+ select IRQ_DOMAIN
bool
config DEBUG_GPIO
@@ -243,6 +244,15 @@ config GPIO_OCTEON
Say yes here to support the on-chip GPIO lines on the OCTEON
family of SOCs.
+config GPIO_OMAP
+ bool "TI OMAP GPIO support" if COMPILE_TEST && !ARCH_OMAP2PLUS
+ default y if ARCH_OMAP
+ depends on ARM
+ select GENERIC_IRQ_CHIP
+ select GPIOLIB_IRQCHIP
+ help
+ Say yes here to enable GPIO support for TI OMAP SoCs.
+
config GPIO_PL061
bool "PrimeCell PL061 GPIO support"
depends on ARM_AMBA
@@ -259,7 +269,7 @@ config GPIO_PXA
config GPIO_RCAR
tristate "Renesas R-Car GPIO"
- depends on ARM
+ depends on ARM && (ARCH_SHMOBILE || COMPILE_TEST)
help
Say yes here to support GPIO on Renesas R-Car SoCs.
@@ -510,6 +520,7 @@ config GPIO_PCA953X
config GPIO_PCA953X_IRQ
bool "Interrupt controller support for PCA953x"
depends on GPIO_PCA953X=y
+ select GPIOLIB_IRQCHIP
help
Say yes here to enable the pca953x to be used as an interrupt
controller. It requires the driver to be built in the kernel.
@@ -579,6 +590,7 @@ config GPIO_STP_XWAY
config GPIO_TC3589X
bool "TC3589X GPIOs"
depends on MFD_TC3589X
+ select GPIOLIB_IRQCHIP
help
This enables support for the GPIOs found on the TC3589X
I/O Expander.
@@ -699,13 +711,13 @@ config GPIO_AMD8111
config GPIO_INTEL_MID
bool "Intel Mid GPIO support"
depends on PCI && X86
- select IRQ_DOMAIN
+ select GPIOLIB_IRQCHIP
help
Say Y here to support Intel Mid GPIO.
config GPIO_PCH
tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7223/ML7831) GPIO"
- depends on PCI && X86
+ depends on PCI && (X86_32 || COMPILE_TEST)
select GENERIC_IRQ_CHIP
help
This driver is for PCH(Platform controller Hub) GPIO of Intel Topcliff
@@ -739,7 +751,7 @@ config GPIO_SODAVILLE
config GPIO_TIMBERDALE
bool "Support for timberdale GPIO IP"
- depends on MFD_TIMBERDALE && HAS_IOMEM
+ depends on MFD_TIMBERDALE
---help---
Add support for the GPIO IP in the timberdale FPGA.
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 6309aff1d806..d10f6a9d875a 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -58,7 +58,7 @@ obj-$(CONFIG_GPIO_MVEBU) += gpio-mvebu.o
obj-$(CONFIG_GPIO_MXC) += gpio-mxc.o
obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o
obj-$(CONFIG_GPIO_OCTEON) += gpio-octeon.o
-obj-$(CONFIG_ARCH_OMAP) += gpio-omap.o
+obj-$(CONFIG_GPIO_OMAP) += gpio-omap.o
obj-$(CONFIG_GPIO_PCA953X) += gpio-pca953x.o
obj-$(CONFIG_GPIO_PCF857X) += gpio-pcf857x.o
obj-$(CONFIG_GPIO_PCH) += gpio-pch.o
diff --git a/drivers/gpio/devres.c b/drivers/gpio/devres.c
index 307464fd015f..65978cf85f79 100644
--- a/drivers/gpio/devres.c
+++ b/drivers/gpio/devres.c
@@ -52,6 +52,22 @@ struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,
EXPORT_SYMBOL(devm_gpiod_get);
/**
+ * devm_gpiod_get_optional - Resource-managed gpiod_get_optional()
+ * @dev: GPIO consumer
+ * @con_id: function within the GPIO consumer
+ *
+ * Managed gpiod_get_optional(). GPIO descriptors returned from this function
+ * are automatically disposed on driver detach. See gpiod_get_optional() for
+ * detailed information about behavior and return values.
+ */
+struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev,
+ const char *con_id)
+{
+ return devm_gpiod_get_index_optional(dev, con_id, 0);
+}
+EXPORT_SYMBOL(devm_gpiod_get_optional);
+
+/**
* devm_gpiod_get_index - Resource-managed gpiod_get_index()
* @dev: GPIO consumer
* @con_id: function within the GPIO consumer
@@ -87,6 +103,33 @@ struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
EXPORT_SYMBOL(devm_gpiod_get_index);
/**
+ * devm_gpiod_get_index_optional - Resource-managed gpiod_get_index_optional()
+ * @dev: GPIO consumer
+ * @con_id: function within the GPIO consumer
+ * @index: index of the GPIO to obtain in the consumer
+ *
+ * Managed gpiod_get_index_optional(). GPIO descriptors returned from this
+ * function are automatically disposed on driver detach. See
+ * gpiod_get_index_optional() for detailed information about behavior and
+ * return values.
+ */
+struct gpio_desc *__must_check devm_gpiod_get_index_optional(struct device *dev,
+ const char *con_id,
+ unsigned int index)
+{
+ struct gpio_desc *desc;
+
+ desc = devm_gpiod_get_index(dev, con_id, index);
+ if (IS_ERR(desc)) {
+ if (PTR_ERR(desc) == -ENOENT)
+ return NULL;
+ }
+
+ return desc;
+}
+EXPORT_SYMBOL(devm_gpiod_get_index_optional);
+
+/**
* devm_gpiod_put - Resource-managed gpiod_put()
* @desc: GPIO descriptor to dispose of
*
diff --git a/drivers/gpio/gpio-adp5520.c b/drivers/gpio/gpio-adp5520.c
index 613265944e2e..f1ade8fa3218 100644
--- a/drivers/gpio/gpio-adp5520.c
+++ b/drivers/gpio/gpio-adp5520.c
@@ -106,10 +106,8 @@ static int adp5520_gpio_probe(struct platform_device *pdev)
}
dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
- if (dev == NULL) {
- dev_err(&pdev->dev, "failed to alloc memory\n");
+ if (dev == NULL)
return -ENOMEM;
- }
dev->master = pdev->dev.parent;
diff --git a/drivers/gpio/gpio-adp5588.c b/drivers/gpio/gpio-adp5588.c
index d974020b78bb..ef19bc33f2bd 100644
--- a/drivers/gpio/gpio-adp5588.c
+++ b/drivers/gpio/gpio-adp5588.c
@@ -379,10 +379,8 @@ static int adp5588_gpio_probe(struct i2c_client *client,
}
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (dev == NULL) {
- dev_err(&client->dev, "failed to alloc memory\n");
+ if (dev == NULL)
return -ENOMEM;
- }
dev->client = client;
diff --git a/drivers/gpio/gpio-bt8xx.c b/drivers/gpio/gpio-bt8xx.c
index ecb3ca2d1d10..6557147d9331 100644
--- a/drivers/gpio/gpio-bt8xx.c
+++ b/drivers/gpio/gpio-bt8xx.c
@@ -178,7 +178,7 @@ static int bt8xxgpio_probe(struct pci_dev *dev,
struct bt8xxgpio *bg;
int err;
- bg = kzalloc(sizeof(*bg), GFP_KERNEL);
+ bg = devm_kzalloc(&dev->dev, sizeof(struct bt8xxgpio), GFP_KERNEL);
if (!bg)
return -ENOMEM;
@@ -188,9 +188,9 @@ static int bt8xxgpio_probe(struct pci_dev *dev,
err = pci_enable_device(dev);
if (err) {
printk(KERN_ERR "bt8xxgpio: Can't enable device.\n");
- goto err_freebg;
+ return err;
}
- if (!request_mem_region(pci_resource_start(dev, 0),
+ if (!devm_request_mem_region(&dev->dev, pci_resource_start(dev, 0),
pci_resource_len(dev, 0),
"bt8xxgpio")) {
printk(KERN_WARNING "bt8xxgpio: Can't request iomem (0x%llx).\n",
@@ -201,11 +201,11 @@ static int bt8xxgpio_probe(struct pci_dev *dev,
pci_set_master(dev);
pci_set_drvdata(dev, bg);
- bg->mmio = ioremap(pci_resource_start(dev, 0), 0x1000);
+ bg->mmio = devm_ioremap(&dev->dev, pci_resource_start(dev, 0), 0x1000);
if (!bg->mmio) {
printk(KERN_ERR "bt8xxgpio: ioremap() failed\n");
err = -EIO;
- goto err_release_mem;
+ goto err_disable;
}
/* Disable interrupts */
@@ -220,18 +220,13 @@ static int bt8xxgpio_probe(struct pci_dev *dev,
err = gpiochip_add(&bg->gpio);
if (err) {
printk(KERN_ERR "bt8xxgpio: Failed to register GPIOs\n");
- goto err_release_mem;
+ goto err_disable;
}
return 0;
-err_release_mem:
- release_mem_region(pci_resource_start(dev, 0),
- pci_resource_len(dev, 0));
err_disable:
pci_disable_device(dev);
-err_freebg:
- kfree(bg);
return err;
}
@@ -250,8 +245,6 @@ static void bt8xxgpio_remove(struct pci_dev *pdev)
release_mem_region(pci_resource_start(pdev, 0),
pci_resource_len(pdev, 0));
pci_disable_device(pdev);
-
- kfree(bg);
}
#ifdef CONFIG_PM
diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c
index 339f9dac591b..9f0682534e2f 100644
--- a/drivers/gpio/gpio-davinci.c
+++ b/drivers/gpio/gpio-davinci.c
@@ -230,10 +230,8 @@ static int davinci_gpio_probe(struct platform_device *pdev)
chips = devm_kzalloc(dev,
ngpio * sizeof(struct davinci_gpio_controller),
GFP_KERNEL);
- if (!chips) {
- dev_err(dev, "Memory allocation failed\n");
+ if (!chips)
return -ENOMEM;
- }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
index ed5711f77e2d..cd3b81435274 100644
--- a/drivers/gpio/gpio-dwapb.c
+++ b/drivers/gpio/gpio-dwapb.c
@@ -198,6 +198,8 @@ static int dwapb_irq_set_type(struct irq_data *d, u32 type)
break;
}
+ irq_setup_alt_chip(d, type);
+
writel(level, gpio->regs + GPIO_INTTYPE_LEVEL);
writel(polarity, gpio->regs + GPIO_INT_POLARITY);
spin_unlock_irqrestore(&bgc->lock, flags);
@@ -213,7 +215,7 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
struct irq_chip_generic *irq_gc;
unsigned int hwirq, ngpio = gc->ngpio;
struct irq_chip_type *ct;
- int err, irq;
+ int err, irq, i;
irq = irq_of_parse_and_map(node, 0);
if (!irq) {
@@ -227,7 +229,7 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
if (!gpio->domain)
return;
- err = irq_alloc_domain_generic_chips(gpio->domain, ngpio, 1,
+ err = irq_alloc_domain_generic_chips(gpio->domain, ngpio, 2,
"gpio-dwapb", handle_level_irq,
IRQ_NOREQUEST, 0,
IRQ_GC_INIT_NESTED_LOCK);
@@ -248,20 +250,24 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
irq_gc->reg_base = gpio->regs;
irq_gc->private = gpio;
- ct = irq_gc->chip_types;
- ct->chip.irq_ack = irq_gc_ack_set_bit;
- ct->chip.irq_mask = irq_gc_mask_set_bit;
- ct->chip.irq_unmask = irq_gc_mask_clr_bit;
- ct->chip.irq_set_type = dwapb_irq_set_type;
- ct->chip.irq_enable = dwapb_irq_enable;
- ct->chip.irq_disable = dwapb_irq_disable;
- ct->chip.irq_request_resources = dwapb_irq_reqres;
- ct->chip.irq_release_resources = dwapb_irq_relres;
- ct->regs.ack = GPIO_PORTA_EOI;
- ct->regs.mask = GPIO_INTMASK;
-
- irq_setup_generic_chip(irq_gc, IRQ_MSK(port->bgc.gc.ngpio),
- IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0);
+ for (i = 0; i < 2; i++) {
+ ct = &irq_gc->chip_types[i];
+ ct->chip.irq_ack = irq_gc_ack_set_bit;
+ ct->chip.irq_mask = irq_gc_mask_set_bit;
+ ct->chip.irq_unmask = irq_gc_mask_clr_bit;
+ ct->chip.irq_set_type = dwapb_irq_set_type;
+ ct->chip.irq_enable = dwapb_irq_enable;
+ ct->chip.irq_disable = dwapb_irq_disable;
+ ct->chip.irq_request_resources = dwapb_irq_reqres;
+ ct->chip.irq_release_resources = dwapb_irq_relres;
+ ct->regs.ack = GPIO_PORTA_EOI;
+ ct->regs.mask = GPIO_INTMASK;
+ ct->type = IRQ_TYPE_LEVEL_MASK;
+ }
+
+ irq_gc->chip_types[0].type = IRQ_TYPE_LEVEL_MASK;
+ irq_gc->chip_types[1].type = IRQ_TYPE_EDGE_BOTH;
+ irq_gc->chip_types[1].handler = handle_edge_irq;
irq_set_chained_handler(irq, dwapb_irq_handler);
irq_set_handler_data(irq, gpio);
diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c
index 8765bd6f48e1..cde36054c387 100644
--- a/drivers/gpio/gpio-em.c
+++ b/drivers/gpio/gpio-em.c
@@ -212,7 +212,7 @@ static void __em_gio_set(struct gpio_chip *chip, unsigned int reg,
{
/* upper 16 bits contains mask and lower 16 actual value */
em_gio_write(gpio_to_priv(chip), reg,
- (1 << (shift + 16)) | (value << shift));
+ (BIT(shift + 16)) | (value << shift));
}
static void em_gio_set(struct gpio_chip *chip, unsigned offset, int value)
@@ -284,7 +284,6 @@ static int em_gio_probe(struct platform_device *pdev)
p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
if (!p) {
- dev_err(&pdev->dev, "failed to allocate driver data\n");
ret = -ENOMEM;
goto err0;
}
diff --git a/drivers/gpio/gpio-ep93xx.c b/drivers/gpio/gpio-ep93xx.c
index 80829f3c6543..dcc2bb4074ef 100644
--- a/drivers/gpio/gpio-ep93xx.c
+++ b/drivers/gpio/gpio-ep93xx.c
@@ -344,37 +344,24 @@ static int ep93xx_gpio_probe(struct platform_device *pdev)
{
struct ep93xx_gpio *ep93xx_gpio;
struct resource *res;
- void __iomem *mmio;
int i;
- int ret;
+ struct device *dev = &pdev->dev;
- ep93xx_gpio = kzalloc(sizeof(*ep93xx_gpio), GFP_KERNEL);
+ ep93xx_gpio = devm_kzalloc(dev, sizeof(struct ep93xx_gpio), GFP_KERNEL);
if (!ep93xx_gpio)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- ret = -ENXIO;
- goto exit_free;
- }
-
- if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
- ret = -EBUSY;
- goto exit_free;
- }
-
- mmio = ioremap(res->start, resource_size(res));
- if (!mmio) {
- ret = -ENXIO;
- goto exit_release;
- }
- ep93xx_gpio->mmio_base = mmio;
+ ep93xx_gpio->mmio_base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(ep93xx_gpio->mmio_base))
+ return PTR_ERR(ep93xx_gpio->mmio_base);
for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_banks); i++) {
struct bgpio_chip *bgc = &ep93xx_gpio->bgc[i];
struct ep93xx_gpio_bank *bank = &ep93xx_gpio_banks[i];
- if (ep93xx_gpio_add_bank(bgc, &pdev->dev, mmio, bank))
+ if (ep93xx_gpio_add_bank(bgc, &pdev->dev,
+ ep93xx_gpio->mmio_base, bank))
dev_warn(&pdev->dev, "Unable to add gpio bank %s\n",
bank->label);
}
@@ -382,13 +369,6 @@ static int ep93xx_gpio_probe(struct platform_device *pdev)
ep93xx_gpio_init_irq();
return 0;
-
-exit_release:
- release_mem_region(res->start, resource_size(res));
-exit_free:
- kfree(ep93xx_gpio);
- dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, ret);
- return ret;
}
static struct platform_driver ep93xx_gpio_driver = {
diff --git a/drivers/gpio/gpio-ge.c b/drivers/gpio/gpio-ge.c
index 7b95a4a8318c..1237a73c3c91 100644
--- a/drivers/gpio/gpio-ge.c
+++ b/drivers/gpio/gpio-ge.c
@@ -18,15 +18,9 @@
*/
#include <linux/kernel.h>
-#include <linux/compiler.h>
-#include <linux/init.h>
#include <linux/io.h>
-#include <linux/of.h>
#include <linux/of_device.h>
-#include <linux/of_platform.h>
#include <linux/of_gpio.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
#include <linux/module.h>
#define GEF_GPIO_DIRECT 0x00
@@ -39,28 +33,26 @@
#define GEF_GPIO_OVERRUN 0x1C
#define GEF_GPIO_MODE 0x20
-static void _gef_gpio_set(void __iomem *reg, unsigned int offset, int value)
+static void gef_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
+ struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
unsigned int data;
- data = ioread32be(reg);
- /* value: 0=low; 1=high */
- if (value & 0x1)
- data = data | (0x1 << offset);
+ data = ioread32be(mmchip->regs + GEF_GPIO_OUT);
+ if (value)
+ data = data | BIT(offset);
else
- data = data & ~(0x1 << offset);
-
- iowrite32be(data, reg);
+ data = data & ~BIT(offset);
+ iowrite32be(data, mmchip->regs + GEF_GPIO_OUT);
}
-
static int gef_gpio_dir_in(struct gpio_chip *chip, unsigned offset)
{
unsigned int data;
struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT);
- data = data | (0x1 << offset);
+ data = data | BIT(offset);
iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT);
return 0;
@@ -71,11 +63,11 @@ static int gef_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value)
unsigned int data;
struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
- /* Set direction before switching to input */
- _gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);
+ /* Set value before switching to output */
+ gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);
data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT);
- data = data & ~(0x1 << offset);
+ data = data & ~BIT(offset);
iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT);
return 0;
@@ -83,116 +75,56 @@ static int gef_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value)
static int gef_gpio_get(struct gpio_chip *chip, unsigned offset)
{
- unsigned int data;
- int state = 0;
struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
- data = ioread32be(mmchip->regs + GEF_GPIO_IN);
- state = (int)((data >> offset) & 0x1);
-
- return state;
+ return !!(ioread32be(mmchip->regs + GEF_GPIO_IN) & BIT(offset));
}
-static void gef_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
- struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
-
- _gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);
-}
+static const struct of_device_id gef_gpio_ids[] = {
+ {
+ .compatible = "gef,sbc610-gpio",
+ .data = (void *)19,
+ }, {
+ .compatible = "gef,sbc310-gpio",
+ .data = (void *)6,
+ }, {
+ .compatible = "ge,imp3a-gpio",
+ .data = (void *)16,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, gef_gpio_ids);
-static int __init gef_gpio_init(void)
+static int __init gef_gpio_probe(struct platform_device *pdev)
{
- struct device_node *np;
- int retval;
- struct of_mm_gpio_chip *gef_gpio_chip;
-
- for_each_compatible_node(np, NULL, "gef,sbc610-gpio") {
-
- pr_debug("%s: Initialising GEF GPIO\n", np->full_name);
-
- /* Allocate chip structure */
- gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
- if (!gef_gpio_chip) {
- pr_err("%s: Unable to allocate structure\n",
- np->full_name);
- continue;
- }
-
- /* Setup pointers to chip functions */
- gef_gpio_chip->gc.of_gpio_n_cells = 2;
- gef_gpio_chip->gc.ngpio = 19;
- gef_gpio_chip->gc.direction_input = gef_gpio_dir_in;
- gef_gpio_chip->gc.direction_output = gef_gpio_dir_out;
- gef_gpio_chip->gc.get = gef_gpio_get;
- gef_gpio_chip->gc.set = gef_gpio_set;
-
- /* This function adds a memory mapped GPIO chip */
- retval = of_mm_gpiochip_add(np, gef_gpio_chip);
- if (retval) {
- kfree(gef_gpio_chip);
- pr_err("%s: Unable to add GPIO\n", np->full_name);
- }
- }
-
- for_each_compatible_node(np, NULL, "gef,sbc310-gpio") {
-
- pr_debug("%s: Initialising GEF GPIO\n", np->full_name);
-
- /* Allocate chip structure */
- gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
- if (!gef_gpio_chip) {
- pr_err("%s: Unable to allocate structure\n",
- np->full_name);
- continue;
- }
-
- /* Setup pointers to chip functions */
- gef_gpio_chip->gc.of_gpio_n_cells = 2;
- gef_gpio_chip->gc.ngpio = 6;
- gef_gpio_chip->gc.direction_input = gef_gpio_dir_in;
- gef_gpio_chip->gc.direction_output = gef_gpio_dir_out;
- gef_gpio_chip->gc.get = gef_gpio_get;
- gef_gpio_chip->gc.set = gef_gpio_set;
-
- /* This function adds a memory mapped GPIO chip */
- retval = of_mm_gpiochip_add(np, gef_gpio_chip);
- if (retval) {
- kfree(gef_gpio_chip);
- pr_err("%s: Unable to add GPIO\n", np->full_name);
- }
- }
-
- for_each_compatible_node(np, NULL, "ge,imp3a-gpio") {
-
- pr_debug("%s: Initialising GE GPIO\n", np->full_name);
-
- /* Allocate chip structure */
- gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
- if (!gef_gpio_chip) {
- pr_err("%s: Unable to allocate structure\n",
- np->full_name);
- continue;
- }
-
- /* Setup pointers to chip functions */
- gef_gpio_chip->gc.of_gpio_n_cells = 2;
- gef_gpio_chip->gc.ngpio = 16;
- gef_gpio_chip->gc.direction_input = gef_gpio_dir_in;
- gef_gpio_chip->gc.direction_output = gef_gpio_dir_out;
- gef_gpio_chip->gc.get = gef_gpio_get;
- gef_gpio_chip->gc.set = gef_gpio_set;
-
- /* This function adds a memory mapped GPIO chip */
- retval = of_mm_gpiochip_add(np, gef_gpio_chip);
- if (retval) {
- kfree(gef_gpio_chip);
- pr_err("%s: Unable to add GPIO\n", np->full_name);
- }
- }
+ const struct of_device_id *of_id =
+ of_match_device(gef_gpio_ids, &pdev->dev);
+ struct of_mm_gpio_chip *mmchip;
+
+ mmchip = devm_kzalloc(&pdev->dev, sizeof(*mmchip), GFP_KERNEL);
+ if (!mmchip)
+ return -ENOMEM;
+
+ /* Setup pointers to chip functions */
+ mmchip->gc.ngpio = (u16)(uintptr_t)of_id->data;
+ mmchip->gc.of_gpio_n_cells = 2;
+ mmchip->gc.direction_input = gef_gpio_dir_in;
+ mmchip->gc.direction_output = gef_gpio_dir_out;
+ mmchip->gc.get = gef_gpio_get;
+ mmchip->gc.set = gef_gpio_set;
+
+ /* This function adds a memory mapped GPIO chip */
+ return of_mm_gpiochip_add(pdev->dev.of_node, mmchip);
+};
- return 0;
+static struct platform_driver gef_gpio_driver = {
+ .driver = {
+ .name = "gef-gpio",
+ .owner = THIS_MODULE,
+ .of_match_table = gef_gpio_ids,
+ },
};
-arch_initcall(gef_gpio_init);
+module_platform_driver_probe(gef_gpio_driver, gef_gpio_probe);
MODULE_DESCRIPTION("GE I/O FPGA GPIO driver");
MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com");
diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-generic.c
index b5dff9e742f8..fea8c82bb8fc 100644
--- a/drivers/gpio/gpio-generic.c
+++ b/drivers/gpio/gpio-generic.c
@@ -388,6 +388,14 @@ static int bgpio_setup_direction(struct bgpio_chip *bgc,
return 0;
}
+static int bgpio_request(struct gpio_chip *chip, unsigned gpio_pin)
+{
+ if (gpio_pin < chip->ngpio)
+ return 0;
+
+ return -EINVAL;
+}
+
int bgpio_remove(struct bgpio_chip *bgc)
{
return gpiochip_remove(&bgc->gc);
@@ -413,6 +421,7 @@ int bgpio_init(struct bgpio_chip *bgc, struct device *dev,
bgc->gc.label = dev_name(dev);
bgc->gc.base = -1;
bgc->gc.ngpio = bgc->bits;
+ bgc->gc.request = bgpio_request;
ret = bgpio_setup_io(bgc, dat, set, clr);
if (ret)
diff --git a/drivers/gpio/gpio-grgpio.c b/drivers/gpio/gpio-grgpio.c
index 84d2478ec294..3c3f515b7916 100644
--- a/drivers/gpio/gpio-grgpio.c
+++ b/drivers/gpio/gpio-grgpio.c
@@ -481,7 +481,7 @@ out:
return ret;
}
-static struct of_device_id grgpio_match[] = {
+static const struct of_device_id grgpio_match[] = {
{.name = "GAISLER_GPIO"},
{.name = "01_01a"},
{},
diff --git a/drivers/gpio/gpio-ich.c b/drivers/gpio/gpio-ich.c
index e73c6755a5eb..70304220a479 100644
--- a/drivers/gpio/gpio-ich.c
+++ b/drivers/gpio/gpio-ich.c
@@ -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 */
diff --git a/drivers/gpio/gpio-janz-ttl.c b/drivers/gpio/gpio-janz-ttl.c
index 2ecd3a09c743..42852eaaf020 100644
--- a/drivers/gpio/gpio-janz-ttl.c
+++ b/drivers/gpio/gpio-janz-ttl.c
@@ -152,34 +152,21 @@ static int ttl_probe(struct platform_device *pdev)
pdata = dev_get_platdata(&pdev->dev);
if (!pdata) {
dev_err(dev, "no platform data\n");
- ret = -ENXIO;
- goto out_return;
+ return -ENXIO;
}
- mod = kzalloc(sizeof(*mod), GFP_KERNEL);
- if (!mod) {
- dev_err(dev, "unable to allocate private data\n");
- ret = -ENOMEM;
- goto out_return;
- }
+ mod = devm_kzalloc(dev, sizeof(*mod), GFP_KERNEL);
+ if (!mod)
+ return -ENOMEM;
platform_set_drvdata(pdev, mod);
spin_lock_init(&mod->lock);
/* get access to the MODULbus registers for this module */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(dev, "MODULbus registers not found\n");
- ret = -ENODEV;
- goto out_free_mod;
- }
-
- mod->regs = ioremap(res->start, resource_size(res));
- if (!mod->regs) {
- dev_err(dev, "MODULbus registers not ioremap\n");
- ret = -ENOMEM;
- goto out_free_mod;
- }
+ mod->regs = devm_ioremap_resource(dev, res);
+ if (IS_ERR(mod->regs))
+ return PTR_ERR(mod->regs);
ttl_setup_device(mod);
@@ -198,17 +185,10 @@ static int ttl_probe(struct platform_device *pdev)
ret = gpiochip_add(gpio);
if (ret) {
dev_err(dev, "unable to add GPIO chip\n");
- goto out_iounmap_regs;
+ return ret;
}
return 0;
-
-out_iounmap_regs:
- iounmap(mod->regs);
-out_free_mod:
- kfree(mod);
-out_return:
- return ret;
}
static int ttl_remove(struct platform_device *pdev)
@@ -223,8 +203,6 @@ static int ttl_remove(struct platform_device *pdev)
return ret;
}
- iounmap(mod->regs);
- kfree(mod);
return 0;
}
diff --git a/drivers/gpio/gpio-kempld.c b/drivers/gpio/gpio-kempld.c
index c6d88173f5a2..1e5e51987d31 100644
--- a/drivers/gpio/gpio-kempld.c
+++ b/drivers/gpio/gpio-kempld.c
@@ -24,7 +24,7 @@
#include <linux/mfd/kempld.h>
#define KEMPLD_GPIO_MAX_NUM 16
-#define KEMPLD_GPIO_MASK(x) (1 << ((x) % 8))
+#define KEMPLD_GPIO_MASK(x) (BIT((x) % 8))
#define KEMPLD_GPIO_DIR_NUM(x) (0x40 + (x) / 8)
#define KEMPLD_GPIO_LVL_NUM(x) (0x42 + (x) / 8)
#define KEMPLD_GPIO_EVT_LVL_EDGE 0x46
@@ -216,4 +216,4 @@ module_platform_driver(kempld_gpio_driver);
MODULE_DESCRIPTION("KEM PLD GPIO Driver");
MODULE_AUTHOR("Michael Brunner <michael.brunner@kontron.com>");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:gpio-kempld");
+MODULE_ALIAS("platform:kempld-gpio");
diff --git a/drivers/gpio/gpio-lynxpoint.c b/drivers/gpio/gpio-lynxpoint.c
index 9a82a9074a2c..2bea89b72508 100644
--- a/drivers/gpio/gpio-lynxpoint.c
+++ b/drivers/gpio/gpio-lynxpoint.c
@@ -375,10 +375,8 @@ static int lp_gpio_probe(struct platform_device *pdev)
int ret = -ENODEV;
lg = devm_kzalloc(dev, sizeof(struct lp_gpio), GFP_KERNEL);
- if (!lg) {
- dev_err(dev, "can't allocate lp_gpio chip data\n");
+ if (!lg)
return -ENOMEM;
- }
lg->pdev = pdev;
platform_set_drvdata(pdev, lg);
diff --git a/drivers/gpio/gpio-max730x.c b/drivers/gpio/gpio-max730x.c
index 8672755f95c9..0814584fcdc1 100644
--- a/drivers/gpio/gpio-max730x.c
+++ b/drivers/gpio/gpio-max730x.c
@@ -237,10 +237,9 @@ int __max730x_remove(struct device *dev)
ts->write(dev, 0x04, 0x00);
ret = gpiochip_remove(&ts->chip);
- if (!ret) {
+ if (!ret)
mutex_destroy(&ts->lock);
- kfree(ts);
- } else
+ else
dev_err(dev, "Failed to remove GPIO controller: %d\n", ret);
return ret;
diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c
index 99a68310e7c0..fe7c0e211f9a 100644
--- a/drivers/gpio/gpio-mcp23s08.c
+++ b/drivers/gpio/gpio-mcp23s08.c
@@ -714,7 +714,7 @@ fail:
#ifdef CONFIG_OF
#ifdef CONFIG_SPI_MASTER
-static struct of_device_id mcp23s08_spi_of_match[] = {
+static const struct of_device_id mcp23s08_spi_of_match[] = {
{
.compatible = "microchip,mcp23s08",
.data = (void *) MCP_TYPE_S08,
@@ -738,7 +738,7 @@ MODULE_DEVICE_TABLE(of, mcp23s08_spi_of_match);
#endif
#if IS_ENABLED(CONFIG_I2C)
-static struct of_device_id mcp23s08_i2c_of_match[] = {
+static const struct of_device_id mcp23s08_i2c_of_match[] = {
{
.compatible = "microchip,mcp23008",
.data = (void *) MCP_TYPE_008,
@@ -867,7 +867,7 @@ static int mcp23s08_probe(struct spi_device *spi)
{
struct mcp23s08_platform_data *pdata;
unsigned addr;
- unsigned chips = 0;
+ int chips = 0;
struct mcp23s08_driver_data *data;
int status, type;
unsigned base = -1,
@@ -895,8 +895,13 @@ static int mcp23s08_probe(struct spi_device *spi)
return -ENODEV;
}
- for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++)
+ for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) {
pullups[addr] = 0;
+ if (spi_present_mask & (1 << addr))
+ chips++;
+ }
+ if (!chips)
+ return -ENODEV;
} else {
type = spi_get_device_id(spi)->driver_data;
pdata = dev_get_platdata(&spi->dev);
@@ -919,12 +924,12 @@ static int mcp23s08_probe(struct spi_device *spi)
pullups[addr] = pdata->chip[addr].pullups;
}
- if (!chips)
- return -ENODEV;
-
base = pdata->base;
}
+ if (!chips)
+ return -ENODEV;
+
data = kzalloc(sizeof(*data) + chips * sizeof(struct mcp23s08),
GFP_KERNEL);
if (!data)
@@ -935,6 +940,10 @@ static int mcp23s08_probe(struct spi_device *spi)
if (!(spi_present_mask & (1 << addr)))
continue;
chips--;
+ if (chips < 0) {
+ dev_err(&spi->dev, "FATAL: invalid negative chip id\n");
+ goto fail;
+ }
data->mcp[addr] = &data->chip[chips];
status = mcp23s08_probe_one(data->mcp[addr], &spi->dev, spi,
0x40 | (addr << 1), type, base,
diff --git a/drivers/gpio/gpio-moxart.c b/drivers/gpio/gpio-moxart.c
index ccd45704e5fd..4661e181be04 100644
--- a/drivers/gpio/gpio-moxart.c
+++ b/drivers/gpio/gpio-moxart.c
@@ -113,10 +113,8 @@ static int moxart_gpio_probe(struct platform_device *pdev)
int ret;
mgc = devm_kzalloc(dev, sizeof(*mgc), GFP_KERNEL);
- if (!mgc) {
- dev_err(dev, "can't allocate GPIO chip container\n");
+ if (!mgc)
return -ENOMEM;
- }
mgc->gpio = moxart_template_chip;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
index d42509422394..418e38650363 100644
--- a/drivers/gpio/gpio-mvebu.c
+++ b/drivers/gpio/gpio-mvebu.c
@@ -535,7 +535,7 @@ static void mvebu_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
#define mvebu_gpio_dbg_show NULL
#endif
-static struct of_device_id mvebu_gpio_of_match[] = {
+static const struct of_device_id mvebu_gpio_of_match[] = {
{
.compatible = "marvell,orion-gpio",
.data = (void *) MVEBU_GPIO_SOC_VARIANT_ORION,
@@ -574,10 +574,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
soc_variant = MVEBU_GPIO_SOC_VARIANT_ORION;
mvchip = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_gpio_chip), GFP_KERNEL);
- if (!mvchip) {
- dev_err(&pdev->dev, "Cannot allocate memory\n");
+ if (!mvchip)
return -ENOMEM;
- }
if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) {
dev_err(&pdev->dev, "Missing ngpios OF property\n");
@@ -738,9 +736,4 @@ static struct platform_driver mvebu_gpio_driver = {
},
.probe = mvebu_gpio_probe,
};
-
-static int __init mvebu_gpio_init(void)
-{
- return platform_driver_register(&mvebu_gpio_driver);
-}
-postcore_initcall(mvebu_gpio_init);
+module_platform_driver(mvebu_gpio_driver);
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index 19b886c21b1d..00f29aa1fb9d 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -24,9 +24,9 @@
#include <linux/pm.h>
#include <linux/of.h>
#include <linux/of_device.h>
-#include <linux/irqdomain.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/gpio.h>
+#include <linux/bitops.h>
#include <linux/platform_data/gpio-omap.h>
#define OFF_MODE 1
@@ -52,7 +52,6 @@ struct gpio_bank {
struct list_head node;
void __iomem *base;
u16 irq;
- struct irq_domain *domain;
u32 non_wakeup_gpios;
u32 enabled_non_wakeup_gpios;
struct gpio_regs context;
@@ -84,22 +83,21 @@ struct gpio_bank {
};
#define GPIO_INDEX(bank, gpio) (gpio % bank->width)
-#define GPIO_BIT(bank, gpio) (1 << GPIO_INDEX(bank, gpio))
+#define GPIO_BIT(bank, gpio) (BIT(GPIO_INDEX(bank, gpio)))
#define GPIO_MOD_CTRL_BIT BIT(0)
#define BANK_USED(bank) (bank->mod_usage || bank->irq_usage)
-#define LINE_USED(line, offset) (line & (1 << offset))
+#define LINE_USED(line, offset) (line & (BIT(offset)))
static int irq_to_gpio(struct gpio_bank *bank, unsigned int gpio_irq)
{
return bank->chip.base + gpio_irq;
}
-static int omap_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+static inline struct gpio_bank *_irq_data_get_bank(struct irq_data *d)
{
- struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip);
-
- return irq_find_mapping(bank->domain, offset);
+ struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
+ return container_of(chip, struct gpio_bank, chip);
}
static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
@@ -110,9 +108,9 @@ static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
reg += bank->regs->direction;
l = readl_relaxed(reg);
if (is_input)
- l |= 1 << gpio;
+ l |= BIT(gpio);
else
- l &= ~(1 << gpio);
+ l &= ~(BIT(gpio));
writel_relaxed(l, reg);
bank->context.oe = l;
}
@@ -155,14 +153,14 @@ static int _get_gpio_datain(struct gpio_bank *bank, int offset)
{
void __iomem *reg = bank->base + bank->regs->datain;
- return (readl_relaxed(reg) & (1 << offset)) != 0;
+ return (readl_relaxed(reg) & (BIT(offset))) != 0;
}
static int _get_gpio_dataout(struct gpio_bank *bank, int offset)
{
void __iomem *reg = bank->base + bank->regs->dataout;
- return (readl_relaxed(reg) & (1 << offset)) != 0;
+ return (readl_relaxed(reg) & (BIT(offset))) != 0;
}
static inline void _gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set)
@@ -180,7 +178,7 @@ static inline void _gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set)
static inline void _gpio_dbck_enable(struct gpio_bank *bank)
{
if (bank->dbck_enable_mask && !bank->dbck_enabled) {
- clk_enable(bank->dbck);
+ clk_prepare_enable(bank->dbck);
bank->dbck_enabled = true;
writel_relaxed(bank->dbck_enable_mask,
@@ -198,7 +196,7 @@ static inline void _gpio_dbck_disable(struct gpio_bank *bank)
*/
writel_relaxed(0, bank->base + bank->regs->debounce_en);
- clk_disable(bank->dbck);
+ clk_disable_unprepare(bank->dbck);
bank->dbck_enabled = false;
}
}
@@ -231,7 +229,7 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
l = GPIO_BIT(bank, gpio);
- clk_enable(bank->dbck);
+ clk_prepare_enable(bank->dbck);
reg = bank->base + bank->regs->debounce;
writel_relaxed(debounce, reg);
@@ -245,7 +243,7 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
bank->dbck_enable_mask = val;
writel_relaxed(val, reg);
- clk_disable(bank->dbck);
+ clk_disable_unprepare(bank->dbck);
/*
* Enable debounce clock per module.
* This call is mandatory because in omap_gpio_request() when
@@ -290,7 +288,7 @@ static void _clear_gpio_debounce(struct gpio_bank *bank, unsigned gpio)
bank->context.debounce = 0;
writel_relaxed(bank->context.debounce, bank->base +
bank->regs->debounce);
- clk_disable(bank->dbck);
+ clk_disable_unprepare(bank->dbck);
bank->dbck_enabled = false;
}
}
@@ -299,7 +297,7 @@ static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio,
unsigned trigger)
{
void __iomem *base = bank->base;
- u32 gpio_bit = 1 << gpio;
+ u32 gpio_bit = BIT(gpio);
_gpio_rmw(base, bank->regs->leveldetect0, gpio_bit,
trigger & IRQ_TYPE_LEVEL_LOW);
@@ -368,9 +366,9 @@ static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)
l = readl_relaxed(reg);
if ((l >> gpio) & 1)
- l &= ~(1 << gpio);
+ l &= ~(BIT(gpio));
else
- l |= 1 << gpio;
+ l |= BIT(gpio);
writel_relaxed(l, reg);
}
@@ -392,11 +390,11 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio,
l = readl_relaxed(reg);
if ((trigger & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
- bank->toggle_mask |= 1 << gpio;
+ bank->toggle_mask |= BIT(gpio);
if (trigger & IRQ_TYPE_EDGE_RISING)
- l |= 1 << gpio;
+ l |= BIT(gpio);
else if (trigger & IRQ_TYPE_EDGE_FALLING)
- l &= ~(1 << gpio);
+ l &= ~(BIT(gpio));
else
return -EINVAL;
@@ -413,10 +411,10 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio,
if (trigger & IRQ_TYPE_EDGE_RISING)
l |= 2 << (gpio << 1);
if (trigger & IRQ_TYPE_EDGE_FALLING)
- l |= 1 << (gpio << 1);
+ l |= BIT(gpio << 1);
/* Enable wake-up during idle for dynamic tick */
- _gpio_rmw(base, bank->regs->wkup_en, 1 << gpio, trigger);
+ _gpio_rmw(base, bank->regs->wkup_en, BIT(gpio), trigger);
bank->context.wake_en =
readl_relaxed(bank->base + bank->regs->wkup_en);
writel_relaxed(l, reg);
@@ -430,7 +428,7 @@ static void _enable_gpio_module(struct gpio_bank *bank, unsigned offset)
void __iomem *reg = bank->base + bank->regs->pinctrl;
/* Claim the pin for MPU */
- writel_relaxed(readl_relaxed(reg) | (1 << offset), reg);
+ writel_relaxed(readl_relaxed(reg) | (BIT(offset)), reg);
}
if (bank->regs->ctrl && !BANK_USED(bank)) {
@@ -453,7 +451,7 @@ static void _disable_gpio_module(struct gpio_bank *bank, unsigned offset)
!LINE_USED(bank->mod_usage, offset) &&
!LINE_USED(bank->irq_usage, offset)) {
/* Disable wake-up during idle for dynamic tick */
- _gpio_rmw(base, bank->regs->wkup_en, 1 << offset, 0);
+ _gpio_rmw(base, bank->regs->wkup_en, BIT(offset), 0);
bank->context.wake_en =
readl_relaxed(bank->base + bank->regs->wkup_en);
}
@@ -479,7 +477,7 @@ static int gpio_is_input(struct gpio_bank *bank, int mask)
static int gpio_irq_type(struct irq_data *d, unsigned type)
{
- struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+ struct gpio_bank *bank = _irq_data_get_bank(d);
unsigned gpio = 0;
int retval;
unsigned long flags;
@@ -509,20 +507,12 @@ static int gpio_irq_type(struct irq_data *d, unsigned type)
if (!LINE_USED(bank->mod_usage, offset)) {
_enable_gpio_module(bank, offset);
_set_gpio_direction(bank, offset, 1);
- } else if (!gpio_is_input(bank, 1 << offset)) {
+ } else if (!gpio_is_input(bank, BIT(offset))) {
spin_unlock_irqrestore(&bank->lock, flags);
return -EINVAL;
}
- retval = gpio_lock_as_irq(&bank->chip, offset);
- if (retval) {
- dev_err(bank->dev, "unable to lock offset %d for IRQ\n",
- offset);
- spin_unlock_irqrestore(&bank->lock, flags);
- return retval;
- }
-
- bank->irq_usage |= 1 << GPIO_INDEX(bank, gpio);
+ bank->irq_usage |= BIT(GPIO_INDEX(bank, gpio));
spin_unlock_irqrestore(&bank->lock, flags);
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
@@ -559,7 +549,7 @@ static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank)
{
void __iomem *reg = bank->base;
u32 l;
- u32 mask = (1 << bank->width) - 1;
+ u32 mask = (BIT(bank->width)) - 1;
reg += bank->regs->irqenable;
l = readl_relaxed(reg);
@@ -664,7 +654,7 @@ static void _reset_gpio(struct gpio_bank *bank, int gpio)
/* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
static int gpio_wake_enable(struct irq_data *d, unsigned int enable)
{
- struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+ struct gpio_bank *bank = _irq_data_get_bank(d);
unsigned int gpio = irq_to_gpio(bank, d->hwirq);
return _set_gpio_wakeup(bank, gpio, enable);
@@ -691,7 +681,7 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
_set_gpio_triggering(bank, offset, IRQ_TYPE_NONE);
_enable_gpio_module(bank, offset);
}
- bank->mod_usage |= 1 << offset;
+ bank->mod_usage |= BIT(offset);
spin_unlock_irqrestore(&bank->lock, flags);
return 0;
@@ -703,7 +693,7 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)
unsigned long flags;
spin_lock_irqsave(&bank->lock, flags);
- bank->mod_usage &= ~(1 << offset);
+ bank->mod_usage &= ~(BIT(offset));
_disable_gpio_module(bank, offset);
_reset_gpio(bank, bank->chip.base + offset);
spin_unlock_irqrestore(&bank->lock, flags);
@@ -732,11 +722,12 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
unsigned int bit;
struct gpio_bank *bank;
int unmasked = 0;
- struct irq_chip *chip = irq_desc_get_chip(desc);
+ struct irq_chip *irqchip = irq_desc_get_chip(desc);
+ struct gpio_chip *chip = irq_get_handler_data(irq);
- chained_irq_enter(chip, desc);
+ chained_irq_enter(irqchip, desc);
- bank = irq_get_handler_data(irq);
+ bank = container_of(chip, struct gpio_bank, chip);
isr_reg = bank->base + bank->regs->irqstatus;
pm_runtime_get_sync(bank->dev);
@@ -764,7 +755,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
configured, we could unmask GPIO bank interrupt immediately */
if (!level_mask && !unmasked) {
unmasked = 1;
- chained_irq_exit(chip, desc);
+ chained_irq_exit(irqchip, desc);
}
if (!isr)
@@ -772,7 +763,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
while (isr) {
bit = __ffs(isr);
- isr &= ~(1 << bit);
+ isr &= ~(BIT(bit));
/*
* Some chips can't respond to both rising and falling
@@ -781,10 +772,11 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
* to respond to the IRQ for the opposite direction.
* This will be indicated in the bank toggle_mask.
*/
- if (bank->toggle_mask & (1 << bit))
+ if (bank->toggle_mask & (BIT(bit)))
_toggle_gpio_edge_triggering(bank, bit);
- generic_handle_irq(irq_find_mapping(bank->domain, bit));
+ generic_handle_irq(irq_find_mapping(bank->chip.irqdomain,
+ bit));
}
}
/* if bank has any level sensitive GPIO pin interrupt
@@ -793,20 +785,20 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
interrupt */
exit:
if (!unmasked)
- chained_irq_exit(chip, desc);
+ chained_irq_exit(irqchip, desc);
pm_runtime_put(bank->dev);
}
static void gpio_irq_shutdown(struct irq_data *d)
{
- struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+ struct gpio_bank *bank = _irq_data_get_bank(d);
unsigned int gpio = irq_to_gpio(bank, d->hwirq);
unsigned long flags;
unsigned offset = GPIO_INDEX(bank, gpio);
spin_lock_irqsave(&bank->lock, flags);
gpio_unlock_as_irq(&bank->chip, offset);
- bank->irq_usage &= ~(1 << offset);
+ bank->irq_usage &= ~(BIT(offset));
_disable_gpio_module(bank, offset);
_reset_gpio(bank, gpio);
spin_unlock_irqrestore(&bank->lock, flags);
@@ -821,7 +813,7 @@ static void gpio_irq_shutdown(struct irq_data *d)
static void gpio_ack_irq(struct irq_data *d)
{
- struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+ struct gpio_bank *bank = _irq_data_get_bank(d);
unsigned int gpio = irq_to_gpio(bank, d->hwirq);
_clear_gpio_irqstatus(bank, gpio);
@@ -829,7 +821,7 @@ static void gpio_ack_irq(struct irq_data *d)
static void gpio_mask_irq(struct irq_data *d)
{
- struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+ struct gpio_bank *bank = _irq_data_get_bank(d);
unsigned int gpio = irq_to_gpio(bank, d->hwirq);
unsigned long flags;
@@ -841,7 +833,7 @@ static void gpio_mask_irq(struct irq_data *d)
static void gpio_unmask_irq(struct irq_data *d)
{
- struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+ struct gpio_bank *bank = _irq_data_get_bank(d);
unsigned int gpio = irq_to_gpio(bank, d->hwirq);
unsigned int irq_mask = GPIO_BIT(bank, gpio);
u32 trigger = irqd_get_trigger_type(d);
@@ -936,6 +928,21 @@ static inline void mpuio_init(struct gpio_bank *bank)
/*---------------------------------------------------------------------*/
+static int gpio_get_direction(struct gpio_chip *chip, unsigned offset)
+{
+ struct gpio_bank *bank;
+ unsigned long flags;
+ void __iomem *reg;
+ int dir;
+
+ bank = container_of(chip, struct gpio_bank, chip);
+ reg = bank->base + bank->regs->direction;
+ spin_lock_irqsave(&bank->lock, flags);
+ dir = !!(readl_relaxed(reg) & BIT(offset));
+ spin_unlock_irqrestore(&bank->lock, flags);
+ return dir;
+}
+
static int gpio_input(struct gpio_chip *chip, unsigned offset)
{
struct gpio_bank *bank;
@@ -954,7 +961,7 @@ static int gpio_get(struct gpio_chip *chip, unsigned offset)
u32 mask;
bank = container_of(chip, struct gpio_bank, chip);
- mask = (1 << offset);
+ mask = (BIT(offset));
if (gpio_is_input(bank, mask))
return _get_gpio_datain(bank, offset);
@@ -1081,10 +1088,12 @@ omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start,
IRQ_NOREQUEST | IRQ_NOPROBE, 0);
}
-static void omap_gpio_chip_init(struct gpio_bank *bank)
+static int omap_gpio_chip_init(struct gpio_bank *bank)
{
int j;
static int gpio;
+ int irq_base = 0;
+ int ret;
/*
* REVISIT eventually switch from OMAP-specific gpio structs
@@ -1092,12 +1101,12 @@ static void omap_gpio_chip_init(struct gpio_bank *bank)
*/
bank->chip.request = omap_gpio_request;
bank->chip.free = omap_gpio_free;
+ bank->chip.get_direction = gpio_get_direction;
bank->chip.direction_input = gpio_input;
bank->chip.get = gpio_get;
bank->chip.direction_output = gpio_output;
bank->chip.set_debounce = gpio_debounce;
bank->chip.set = gpio_set;
- bank->chip.to_irq = omap_gpio_to_irq;
if (bank->is_mpuio) {
bank->chip.label = "mpuio";
if (bank->regs->wkup_en)
@@ -1110,22 +1119,48 @@ static void omap_gpio_chip_init(struct gpio_bank *bank)
}
bank->chip.ngpio = bank->width;
- gpiochip_add(&bank->chip);
+ ret = gpiochip_add(&bank->chip);
+ if (ret) {
+ dev_err(bank->dev, "Could not register gpio chip %d\n", ret);
+ return ret;
+ }
+
+#ifdef CONFIG_ARCH_OMAP1
+ /*
+ * REVISIT: Once we have OMAP1 supporting SPARSE_IRQ, we can drop
+ * irq_alloc_descs() since a base IRQ offset will no longer be needed.
+ */
+ irq_base = irq_alloc_descs(-1, 0, bank->width, 0);
+ if (irq_base < 0) {
+ dev_err(bank->dev, "Couldn't allocate IRQ numbers\n");
+ return -ENODEV;
+ }
+#endif
+
+ ret = gpiochip_irqchip_add(&bank->chip, &gpio_irq_chip,
+ irq_base, gpio_irq_handler,
+ IRQ_TYPE_NONE);
+
+ if (ret) {
+ dev_err(bank->dev, "Couldn't add irqchip to gpiochip %d\n", ret);
+ ret = gpiochip_remove(&bank->chip);
+ return -ENODEV;
+ }
+
+ gpiochip_set_chained_irqchip(&bank->chip, &gpio_irq_chip,
+ bank->irq, gpio_irq_handler);
for (j = 0; j < bank->width; j++) {
- int irq = irq_create_mapping(bank->domain, j);
+ int irq = irq_find_mapping(bank->chip.irqdomain, j);
irq_set_lockdep_class(irq, &gpio_lock_class);
- irq_set_chip_data(irq, bank);
if (bank->is_mpuio) {
omap_mpuio_alloc_gc(bank, irq, bank->width);
- } else {
- irq_set_chip_and_handler(irq, &gpio_irq_chip,
- handle_simple_irq);
- set_irq_flags(irq, IRQF_VALID);
+ irq_set_chip_and_handler(irq, NULL, NULL);
+ set_irq_flags(irq, 0);
}
}
- irq_set_chained_handler(bank->irq, gpio_irq_handler);
- irq_set_handler_data(bank->irq, bank);
+
+ return 0;
}
static const struct of_device_id omap_gpio_match[];
@@ -1138,9 +1173,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
const struct omap_gpio_platform_data *pdata;
struct resource *res;
struct gpio_bank *bank;
-#ifdef CONFIG_ARCH_OMAP1
- int irq_base;
-#endif
+ int ret;
match = of_match_device(of_match_ptr(omap_gpio_match), dev);
@@ -1162,6 +1195,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
bank->irq = res->start;
bank->dev = dev;
+ bank->chip.dev = dev;
bank->dbck_flag = pdata->dbck_flag;
bank->stride = pdata->bank_stride;
bank->width = pdata->bank_width;
@@ -1182,29 +1216,6 @@ static int omap_gpio_probe(struct platform_device *pdev)
pdata->get_context_loss_count;
}
-#ifdef CONFIG_ARCH_OMAP1
- /*
- * REVISIT: Once we have OMAP1 supporting SPARSE_IRQ, we can drop
- * irq_alloc_descs() and irq_domain_add_legacy() and just use a
- * linear IRQ domain mapping for all OMAP platforms.
- */
- irq_base = irq_alloc_descs(-1, 0, bank->width, 0);
- if (irq_base < 0) {
- dev_err(dev, "Couldn't allocate IRQ numbers\n");
- return -ENODEV;
- }
-
- bank->domain = irq_domain_add_legacy(node, bank->width, irq_base,
- 0, &irq_domain_simple_ops, NULL);
-#else
- bank->domain = irq_domain_add_linear(node, bank->width,
- &irq_domain_simple_ops, NULL);
-#endif
- if (!bank->domain) {
- dev_err(dev, "Couldn't register an IRQ domain\n");
- return -ENODEV;
- }
-
if (bank->regs->set_dataout && bank->regs->clr_dataout)
bank->set_dataout = _set_gpio_dataout_reg;
else
@@ -1216,7 +1227,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
bank->base = devm_ioremap_resource(dev, res);
if (IS_ERR(bank->base)) {
- irq_domain_remove(bank->domain);
+ irq_domain_remove(bank->chip.irqdomain);
return PTR_ERR(bank->base);
}
@@ -1230,7 +1241,11 @@ static int omap_gpio_probe(struct platform_device *pdev)
mpuio_init(bank);
omap_gpio_mod_init(bank);
- omap_gpio_chip_init(bank);
+
+ ret = omap_gpio_chip_init(bank);
+ if (ret)
+ return ret;
+
omap_gpio_show_rev(bank);
pm_runtime_put(bank->dev);
diff --git a/drivers/gpio/gpio-palmas.c b/drivers/gpio/gpio-palmas.c
index da9d33252e56..86bdbe362068 100644
--- a/drivers/gpio/gpio-palmas.c
+++ b/drivers/gpio/gpio-palmas.c
@@ -148,7 +148,7 @@ static const struct palmas_device_data tps80036_dev_data = {
.ngpio = 16,
};
-static struct of_device_id of_palmas_gpio_match[] = {
+static const struct of_device_id of_palmas_gpio_match[] = {
{ .compatible = "ti,palmas-gpio", .data = &palmas_dev_data,},
{ .compatible = "ti,tps65913-gpio", .data = &palmas_dev_data,},
{ .compatible = "ti,tps65914-gpio", .data = &palmas_dev_data,},
@@ -173,10 +173,8 @@ static int palmas_gpio_probe(struct platform_device *pdev)
palmas_gpio = devm_kzalloc(&pdev->dev,
sizeof(*palmas_gpio), GFP_KERNEL);
- if (!palmas_gpio) {
- dev_err(&pdev->dev, "Could not allocate palmas_gpio\n");
+ if (!palmas_gpio)
return -ENOMEM;
- }
palmas_gpio->palmas = palmas;
palmas_gpio->gpio_chip.owner = THIS_MODULE;
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index d550d8e58705..e721a37c3473 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -15,8 +15,6 @@
#include <linux/init.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/irqdomain.h>
#include <linux/i2c.h>
#include <linux/platform_data/pca953x.h>
#include <linux/slab.h>
@@ -91,7 +89,6 @@ struct pca953x_chip {
u8 irq_stat[MAX_BANK];
u8 irq_trig_raise[MAX_BANK];
u8 irq_trig_fall[MAX_BANK];
- struct irq_domain *domain;
#endif
struct i2c_client *client;
@@ -100,6 +97,11 @@ struct pca953x_chip {
int chip_type;
};
+static inline struct pca953x_chip *to_pca(struct gpio_chip *gc)
+{
+ return container_of(gc, struct pca953x_chip, gpio_chip);
+}
+
static int pca953x_read_single(struct pca953x_chip *chip, int reg, u32 *val,
int off)
{
@@ -202,12 +204,10 @@ static int pca953x_read_regs(struct pca953x_chip *chip, int reg, u8 *val)
static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
{
- struct pca953x_chip *chip;
+ struct pca953x_chip *chip = to_pca(gc);
u8 reg_val;
int ret, offset = 0;
- chip = container_of(gc, struct pca953x_chip, gpio_chip);
-
mutex_lock(&chip->i2c_lock);
reg_val = chip->reg_direction[off / BANK_SZ] | (1u << (off % BANK_SZ));
@@ -233,12 +233,10 @@ exit:
static int pca953x_gpio_direction_output(struct gpio_chip *gc,
unsigned off, int val)
{
- struct pca953x_chip *chip;
+ struct pca953x_chip *chip = to_pca(gc);
u8 reg_val;
int ret, offset = 0;
- chip = container_of(gc, struct pca953x_chip, gpio_chip);
-
mutex_lock(&chip->i2c_lock);
/* set output level */
if (val)
@@ -285,12 +283,10 @@ exit:
static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
{
- struct pca953x_chip *chip;
+ struct pca953x_chip *chip = to_pca(gc);
u32 reg_val;
int ret, offset = 0;
- chip = container_of(gc, struct pca953x_chip, gpio_chip);
-
mutex_lock(&chip->i2c_lock);
switch (chip->chip_type) {
case PCA953X_TYPE:
@@ -315,12 +311,10 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
{
- struct pca953x_chip *chip;
+ struct pca953x_chip *chip = to_pca(gc);
u8 reg_val;
int ret, offset = 0;
- chip = container_of(gc, struct pca953x_chip, gpio_chip);
-
mutex_lock(&chip->i2c_lock);
if (val)
reg_val = chip->reg_output[off / BANK_SZ]
@@ -367,38 +361,34 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
}
#ifdef CONFIG_GPIO_PCA953X_IRQ
-static int pca953x_gpio_to_irq(struct gpio_chip *gc, unsigned off)
-{
- struct pca953x_chip *chip;
-
- chip = container_of(gc, struct pca953x_chip, gpio_chip);
- return irq_create_mapping(chip->domain, off);
-}
-
static void pca953x_irq_mask(struct irq_data *d)
{
- struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct pca953x_chip *chip = to_pca(gc);
chip->irq_mask[d->hwirq / BANK_SZ] &= ~(1 << (d->hwirq % BANK_SZ));
}
static void pca953x_irq_unmask(struct irq_data *d)
{
- struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct pca953x_chip *chip = to_pca(gc);
chip->irq_mask[d->hwirq / BANK_SZ] |= 1 << (d->hwirq % BANK_SZ);
}
static void pca953x_irq_bus_lock(struct irq_data *d)
{
- struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct pca953x_chip *chip = to_pca(gc);
mutex_lock(&chip->irq_lock);
}
static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
{
- struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct pca953x_chip *chip = to_pca(gc);
u8 new_irqs;
int level, i;
@@ -420,7 +410,8 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
static int pca953x_irq_set_type(struct irq_data *d, unsigned int type)
{
- struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct pca953x_chip *chip = to_pca(gc);
int bank_nb = d->hwirq / BANK_SZ;
u8 mask = 1 << (d->hwirq % BANK_SZ);
@@ -503,44 +494,25 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid)
struct pca953x_chip *chip = devid;
u8 pending[MAX_BANK];
u8 level;
+ unsigned nhandled = 0;
int i;
if (!pca953x_irq_pending(chip, pending))
- return IRQ_HANDLED;
+ return IRQ_NONE;
for (i = 0; i < NBANK(chip); i++) {
while (pending[i]) {
level = __ffs(pending[i]);
- handle_nested_irq(irq_find_mapping(chip->domain,
+ handle_nested_irq(irq_find_mapping(chip->gpio_chip.irqdomain,
level + (BANK_SZ * i)));
pending[i] &= ~(1 << level);
+ nhandled++;
}
}
- return IRQ_HANDLED;
+ return (nhandled > 0) ? IRQ_HANDLED : IRQ_NONE;
}
-static int pca953x_gpio_irq_map(struct irq_domain *d, unsigned int irq,
- irq_hw_number_t hwirq)
-{
- irq_clear_status_flags(irq, IRQ_NOREQUEST);
- irq_set_chip_data(irq, d->host_data);
- irq_set_chip(irq, &pca953x_irq_chip);
- irq_set_nested_thread(irq, true);
-#ifdef CONFIG_ARM
- set_irq_flags(irq, IRQF_VALID);
-#else
- irq_set_noprobe(irq);
-#endif
-
- return 0;
-}
-
-static const struct irq_domain_ops pca953x_irq_simple_ops = {
- .map = pca953x_gpio_irq_map,
- .xlate = irq_domain_xlate_twocell,
-};
-
static int pca953x_irq_setup(struct pca953x_chip *chip,
const struct i2c_device_id *id,
int irq_base)
@@ -572,19 +544,12 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
chip->irq_stat[i] &= chip->reg_direction[i];
mutex_init(&chip->irq_lock);
- chip->domain = irq_domain_add_simple(client->dev.of_node,
- chip->gpio_chip.ngpio,
- irq_base,
- &pca953x_irq_simple_ops,
- chip);
- if (!chip->domain)
- return -ENODEV;
-
ret = devm_request_threaded_irq(&client->dev,
client->irq,
NULL,
pca953x_irq_handler,
- IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT |
+ IRQF_SHARED,
dev_name(&client->dev), chip);
if (ret) {
dev_err(&client->dev, "failed to request irq %d\n",
@@ -592,7 +557,16 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
return ret;
}
- chip->gpio_chip.to_irq = pca953x_gpio_to_irq;
+ ret = gpiochip_irqchip_add(&chip->gpio_chip,
+ &pca953x_irq_chip,
+ irq_base,
+ handle_simple_irq,
+ IRQ_TYPE_NONE);
+ if (ret) {
+ dev_err(&client->dev,
+ "could not connect irqchip to gpiochip\n");
+ return ret;
+ }
}
return 0;
@@ -756,11 +730,11 @@ static int pca953x_probe(struct i2c_client *client,
if (ret)
return ret;
- ret = pca953x_irq_setup(chip, id, irq_base);
+ ret = gpiochip_add(&chip->gpio_chip);
if (ret)
return ret;
- ret = gpiochip_add(&chip->gpio_chip);
+ ret = pca953x_irq_setup(chip, id, irq_base);
if (ret)
return ret;
diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c
index 82735822bc9d..27b46751ea7e 100644
--- a/drivers/gpio/gpio-pcf857x.c
+++ b/drivers/gpio/gpio-pcf857x.c
@@ -262,7 +262,7 @@ static int pcf857x_irq_domain_init(struct pcf857x *gpio,
/* enable real irq */
status = devm_request_threaded_irq(&client->dev, client->irq,
NULL, pcf857x_irq, IRQF_ONESHOT |
- IRQF_TRIGGER_FALLING,
+ IRQF_TRIGGER_FALLING | IRQF_SHARED,
dev_name(&client->dev), gpio);
if (status)
@@ -319,7 +319,7 @@ static int pcf857x_probe(struct i2c_client *client,
status = pcf857x_irq_domain_init(gpio, client);
if (status < 0) {
dev_err(&client->dev, "irq_domain init failed\n");
- goto fail;
+ goto fail_irq_domain;
}
}
@@ -414,12 +414,13 @@ static int pcf857x_probe(struct i2c_client *client,
return 0;
fail:
- dev_dbg(&client->dev, "probe error %d for '%s'\n",
- status, client->name);
-
if (client->irq)
pcf857x_irq_domain_cleanup(gpio);
+fail_irq_domain:
+ dev_dbg(&client->dev, "probe error %d for '%s'\n",
+ status, client->name);
+
return status;
}
diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c
index 83a156397474..d6eac9b17db9 100644
--- a/drivers/gpio/gpio-pch.c
+++ b/drivers/gpio/gpio-pch.c
@@ -20,6 +20,7 @@
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <linux/slab.h>
#define PCH_EDGE_FALLING 0
#define PCH_EDGE_RISING BIT(0)
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c
index b0f475243cef..84b49cfb81a8 100644
--- a/drivers/gpio/gpio-pl061.c
+++ b/drivers/gpio/gpio-pl061.c
@@ -17,7 +17,6 @@
#include <linux/irq.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/bitops.h>
-#include <linux/workqueue.h>
#include <linux/gpio.h>
#include <linux/device.h>
#include <linux/amba/bus.h>
@@ -88,7 +87,7 @@ static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)
spin_lock_irqsave(&chip->lock, flags);
gpiodir = readb(chip->base + GPIODIR);
- gpiodir &= ~(1 << offset);
+ gpiodir &= ~(BIT(offset));
writeb(gpiodir, chip->base + GPIODIR);
spin_unlock_irqrestore(&chip->lock, flags);
@@ -106,16 +105,16 @@ static int pl061_direction_output(struct gpio_chip *gc, unsigned offset,
return -EINVAL;
spin_lock_irqsave(&chip->lock, flags);
- writeb(!!value << offset, chip->base + (1 << (offset + 2)));
+ writeb(!!value << offset, chip->base + (BIT(offset + 2)));
gpiodir = readb(chip->base + GPIODIR);
- gpiodir |= 1 << offset;
+ gpiodir |= BIT(offset);
writeb(gpiodir, chip->base + GPIODIR);
/*
* gpio value is set again, because pl061 doesn't allow to set value of
* a gpio pin before configuring it in OUT mode.
*/
- writeb(!!value << offset, chip->base + (1 << (offset + 2)));
+ writeb(!!value << offset, chip->base + (BIT(offset + 2)));
spin_unlock_irqrestore(&chip->lock, flags);
return 0;
@@ -125,14 +124,14 @@ static int pl061_get_value(struct gpio_chip *gc, unsigned offset)
{
struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
- return !!readb(chip->base + (1 << (offset + 2)));
+ return !!readb(chip->base + (BIT(offset + 2)));
}
static void pl061_set_value(struct gpio_chip *gc, unsigned offset, int value)
{
struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
- writeb(!!value << offset, chip->base + (1 << (offset + 2)));
+ writeb(!!value << offset, chip->base + (BIT(offset + 2)));
}
static int pl061_irq_type(struct irq_data *d, unsigned trigger)
@@ -207,7 +206,7 @@ static void pl061_irq_mask(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
- u8 mask = 1 << (irqd_to_hwirq(d) % PL061_GPIO_NR);
+ u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);
u8 gpioie;
spin_lock(&chip->lock);
@@ -220,7 +219,7 @@ static void pl061_irq_unmask(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
- u8 mask = 1 << (irqd_to_hwirq(d) % PL061_GPIO_NR);
+ u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);
u8 gpioie;
spin_lock(&chip->lock);
@@ -302,9 +301,9 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
for (i = 0; i < PL061_GPIO_NR; i++) {
if (pdata) {
- if (pdata->directions & (1 << i))
+ if (pdata->directions & (BIT(i)))
pl061_direction_output(&chip->gc, i,
- pdata->values & (1 << i));
+ pdata->values & (BIT(i)));
else
pl061_direction_input(&chip->gc, i);
}
@@ -331,7 +330,7 @@ static int pl061_suspend(struct device *dev)
chip->csave_regs.gpio_ie = readb(chip->base + GPIOIE);
for (offset = 0; offset < PL061_GPIO_NR; offset++) {
- if (chip->csave_regs.gpio_dir & (1 << offset))
+ if (chip->csave_regs.gpio_dir & (BIT(offset)))
chip->csave_regs.gpio_data |=
pl061_get_value(&chip->gc, offset) << offset;
}
@@ -345,10 +344,10 @@ static int pl061_resume(struct device *dev)
int offset;
for (offset = 0; offset < PL061_GPIO_NR; offset++) {
- if (chip->csave_regs.gpio_dir & (1 << offset))
+ if (chip->csave_regs.gpio_dir & (BIT(offset)))
pl061_direction_output(&chip->gc, offset,
chip->csave_regs.gpio_data &
- (1 << offset));
+ (BIT(offset)));
else
pl061_direction_input(&chip->gc, offset);
}
diff --git a/drivers/gpio/gpio-rc5t583.c b/drivers/gpio/gpio-rc5t583.c
index 9b423173ab50..562b0c4d9cc8 100644
--- a/drivers/gpio/gpio-rc5t583.c
+++ b/drivers/gpio/gpio-rc5t583.c
@@ -119,10 +119,8 @@ static int rc5t583_gpio_probe(struct platform_device *pdev)
rc5t583_gpio = devm_kzalloc(&pdev->dev, sizeof(*rc5t583_gpio),
GFP_KERNEL);
- if (!rc5t583_gpio) {
- dev_warn(&pdev->dev, "Mem allocation for rc5t583_gpio failed");
+ if (!rc5t583_gpio)
return -ENOMEM;
- }
rc5t583_gpio->gpio_chip.label = "gpio-rc5t583",
rc5t583_gpio->gpio_chip.owner = THIS_MODULE,
diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c
index 03c91482432c..0c9f803fc1ac 100644
--- a/drivers/gpio/gpio-rcar.c
+++ b/drivers/gpio/gpio-rcar.c
@@ -26,6 +26,7 @@
#include <linux/pinctrl/consumer.h>
#include <linux/platform_data/gpio-rcar.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
@@ -362,7 +363,6 @@ static int gpio_rcar_probe(struct platform_device *pdev)
p = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL);
if (!p) {
- dev_err(dev, "failed to allocate driver data\n");
ret = -ENOMEM;
goto err0;
}
@@ -377,6 +377,9 @@ static int gpio_rcar_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, p);
+ pm_runtime_enable(dev);
+ pm_runtime_get_sync(dev);
+
io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
@@ -460,6 +463,8 @@ static int gpio_rcar_probe(struct platform_device *pdev)
err1:
irq_domain_remove(p->irq_domain);
err0:
+ pm_runtime_put(dev);
+ pm_runtime_disable(dev);
return ret;
}
@@ -473,6 +478,8 @@ static int gpio_rcar_remove(struct platform_device *pdev)
return ret;
irq_domain_remove(p->irq_domain);
+ pm_runtime_put(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
return 0;
}
diff --git a/drivers/gpio/gpio-rdc321x.c b/drivers/gpio/gpio-rdc321x.c
index 88577c3272a5..9fa7e53331c9 100644
--- a/drivers/gpio/gpio-rdc321x.c
+++ b/drivers/gpio/gpio-rdc321x.c
@@ -141,17 +141,15 @@ static int rdc321x_gpio_probe(struct platform_device *pdev)
return -ENODEV;
}
- rdc321x_gpio_dev = kzalloc(sizeof(struct rdc321x_gpio), GFP_KERNEL);
- if (!rdc321x_gpio_dev) {
- dev_err(&pdev->dev, "failed to allocate private data\n");
+ rdc321x_gpio_dev = devm_kzalloc(&pdev->dev, sizeof(struct rdc321x_gpio),
+ GFP_KERNEL);
+ if (!rdc321x_gpio_dev)
return -ENOMEM;
- }
r = platform_get_resource_byname(pdev, IORESOURCE_IO, "gpio-reg1");
if (!r) {
dev_err(&pdev->dev, "failed to get gpio-reg1 resource\n");
- err = -ENODEV;
- goto out_free;
+ return -ENODEV;
}
spin_lock_init(&rdc321x_gpio_dev->lock);
@@ -162,8 +160,7 @@ static int rdc321x_gpio_probe(struct platform_device *pdev)
r = platform_get_resource_byname(pdev, IORESOURCE_IO, "gpio-reg2");
if (!r) {
dev_err(&pdev->dev, "failed to get gpio-reg2 resource\n");
- err = -ENODEV;
- goto out_free;
+ return -ENODEV;
}
rdc321x_gpio_dev->reg2_ctrl_base = r->start;
@@ -187,21 +184,17 @@ static int rdc321x_gpio_probe(struct platform_device *pdev)
rdc321x_gpio_dev->reg1_data_base,
&rdc321x_gpio_dev->data_reg[0]);
if (err)
- goto out_free;
+ return err;
err = pci_read_config_dword(rdc321x_gpio_dev->sb_pdev,
rdc321x_gpio_dev->reg2_data_base,
&rdc321x_gpio_dev->data_reg[1]);
if (err)
- goto out_free;
+ return err;
dev_info(&pdev->dev, "registering %d GPIOs\n",
rdc321x_gpio_dev->chip.ngpio);
return gpiochip_add(&rdc321x_gpio_dev->chip);
-
-out_free:
- kfree(rdc321x_gpio_dev);
- return err;
}
static int rdc321x_gpio_remove(struct platform_device *pdev)
@@ -213,8 +206,6 @@ static int rdc321x_gpio_remove(struct platform_device *pdev)
if (ret)
dev_err(&pdev->dev, "failed to unregister chip\n");
- kfree(rdc321x_gpio_dev);
-
return ret;
}
diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c
index 5af65719b95d..a9b1cd16c848 100644
--- a/drivers/gpio/gpio-sch.c
+++ b/drivers/gpio/gpio-sch.c
@@ -97,8 +97,6 @@ static int sch_gpio_core_direction_out(struct gpio_chip *gc,
u8 curr_dirs;
unsigned short offset, bit;
- sch_gpio_core_set(gc, gpio_num, val);
-
spin_lock(&gpio_lock);
offset = CGIO + gpio_num / 8;
@@ -109,6 +107,17 @@ static int sch_gpio_core_direction_out(struct gpio_chip *gc,
outb(curr_dirs & ~(1 << bit), gpio_ba + offset);
spin_unlock(&gpio_lock);
+
+ /*
+ * according to the datasheet, writing to the level register has no
+ * effect when GPIO is programmed as input.
+ * Actually the the level register is read-only when configured as input.
+ * Thus presetting the output level before switching to output is _NOT_ possible.
+ * Hence we set the level after configuring the GPIO as output.
+ * But we cannot prevent a short low pulse if direction is set to high
+ * and an external pull-up is connected.
+ */
+ sch_gpio_core_set(gc, gpio_num, val);
return 0;
}
@@ -178,8 +187,6 @@ static int sch_gpio_resume_direction_out(struct gpio_chip *gc,
u8 curr_dirs;
unsigned short offset, bit;
- sch_gpio_resume_set(gc, gpio_num, val);
-
offset = RGIO + gpio_num / 8;
bit = gpio_num % 8;
@@ -190,6 +197,17 @@ static int sch_gpio_resume_direction_out(struct gpio_chip *gc,
outb(curr_dirs & ~(1 << bit), gpio_ba + offset);
spin_unlock(&gpio_lock);
+
+ /*
+ * according to the datasheet, writing to the level register has no
+ * effect when GPIO is programmed as input.
+ * Actually the the level register is read-only when configured as input.
+ * Thus presetting the output level before switching to output is _NOT_ possible.
+ * Hence we set the level after configuring the GPIO as output.
+ * But we cannot prevent a short low pulse if direction is set to high
+ * and an external pull-up is connected.
+ */
+ sch_gpio_resume_set(gc, gpio_num, val);
return 0;
}
diff --git a/drivers/gpio/gpio-sch311x.c b/drivers/gpio/gpio-sch311x.c
index 0357387b3645..f942b80ee403 100644
--- a/drivers/gpio/gpio-sch311x.c
+++ b/drivers/gpio/gpio-sch311x.c
@@ -327,14 +327,22 @@ static int __init sch311x_detect(int sio_config_port, unsigned short *addr)
if (err)
return err;
- /* Check device ID. We currently know about:
- * SCH3112 (0x7c), SCH3114 (0x7d), and SCH3116 (0x7f). */
+ /* Check device ID. */
reg = sch311x_sio_inb(sio_config_port, 0x20);
- if (!(reg == 0x7c || reg == 0x7d || reg == 0x7f)) {
+ switch (reg) {
+ case 0x7c: /* SCH3112 */
+ dev_id = 2;
+ break;
+ case 0x7d: /* SCH3114 */
+ dev_id = 4;
+ break;
+ case 0x7f: /* SCH3116 */
+ dev_id = 6;
+ break;
+ default:
err = -ENODEV;
goto exit;
}
- dev_id = reg == 0x7c ? 2 : reg == 0x7d ? 4 : 6;
/* Select logical device A (runtime registers) */
sch311x_sio_outb(sio_config_port, 0x07, 0x0a);
diff --git a/drivers/gpio/gpio-spear-spics.c b/drivers/gpio/gpio-spear-spics.c
index e9a0415834ea..353263c85d26 100644
--- a/drivers/gpio/gpio-spear-spics.c
+++ b/drivers/gpio/gpio-spear-spics.c
@@ -2,7 +2,7 @@
* SPEAr platform SPI chipselect abstraction over gpiolib
*
* Copyright (C) 2012 ST Microelectronics
- * Shiraz Hashim <shiraz.hashim@st.com>
+ * Shiraz Hashim <shiraz.linux.kernel@gmail.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
@@ -129,10 +129,8 @@ static int spics_gpio_probe(struct platform_device *pdev)
int ret;
spics = devm_kzalloc(&pdev->dev, sizeof(*spics), GFP_KERNEL);
- if (!spics) {
- dev_err(&pdev->dev, "memory allocation fail\n");
+ if (!spics)
return -ENOMEM;
- }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
spics->base = devm_ioremap_resource(&pdev->dev, res);
@@ -205,6 +203,6 @@ static int __init spics_gpio_init(void)
}
subsys_initcall(spics_gpio_init);
-MODULE_AUTHOR("Shiraz Hashim <shiraz.hashim@st.com>");
+MODULE_AUTHOR("Shiraz Hashim <shiraz.linux.kernel@gmail.com>");
MODULE_DESCRIPTION("ST Microlectronics SPEAr SPI Chip Select Abstraction");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-sx150x.c b/drivers/gpio/gpio-sx150x.c
index 13d73fb2b5e1..b51ca9f5c140 100644
--- a/drivers/gpio/gpio-sx150x.c
+++ b/drivers/gpio/gpio-sx150x.c
@@ -22,7 +22,6 @@
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/slab.h>
-#include <linux/workqueue.h>
#include <linux/i2c/sx150x.h>
#define NO_UPDATE_PENDING -1
diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c
index 1019320984d7..51f7cbd9ff71 100644
--- a/drivers/gpio/gpio-tc3589x.c
+++ b/drivers/gpio/gpio-tc3589x.c
@@ -12,8 +12,6 @@
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/of.h>
-#include <linux/irq.h>
-#include <linux/irqdomain.h>
#include <linux/interrupt.h>
#include <linux/mfd/tc3589x.h>
@@ -31,10 +29,6 @@ struct tc3589x_gpio {
struct tc3589x *tc3589x;
struct device *dev;
struct mutex irq_lock;
- struct irq_domain *domain;
-
- int irq_base;
-
/* Caches of interrupt control registers for bus_lock */
u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS];
u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS];
@@ -95,30 +89,6 @@ static int tc3589x_gpio_direction_input(struct gpio_chip *chip,
return tc3589x_set_bits(tc3589x, reg, 1 << pos, 0);
}
-/**
- * tc3589x_gpio_irq_get_irq(): Map a hardware IRQ on a chip to a Linux IRQ
- *
- * @tc3589x_gpio: tc3589x_gpio_irq controller to operate on.
- * @irq: index of the hardware interrupt requested in the chip IRQs
- *
- * Useful for drivers to request their own IRQs.
- */
-static int tc3589x_gpio_irq_get_irq(struct tc3589x_gpio *tc3589x_gpio,
- int hwirq)
-{
- if (!tc3589x_gpio)
- return -EINVAL;
-
- return irq_create_mapping(tc3589x_gpio->domain, hwirq);
-}
-
-static int tc3589x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
- struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
-
- return tc3589x_gpio_irq_get_irq(tc3589x_gpio, offset);
-}
-
static struct gpio_chip template_chip = {
.label = "tc3589x",
.owner = THIS_MODULE,
@@ -126,13 +96,13 @@ static struct gpio_chip template_chip = {
.get = tc3589x_gpio_get,
.direction_output = tc3589x_gpio_direction_output,
.set = tc3589x_gpio_set,
- .to_irq = tc3589x_gpio_to_irq,
.can_sleep = true,
};
static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type)
{
- struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);
int offset = d->hwirq;
int regoffset = offset / 8;
int mask = 1 << (offset % 8);
@@ -159,14 +129,16 @@ static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type)
static void tc3589x_gpio_irq_lock(struct irq_data *d)
{
- struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);
mutex_lock(&tc3589x_gpio->irq_lock);
}
static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d)
{
- struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);
struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
static const u8 regmap[] = {
[REG_IBE] = TC3589x_GPIOIBE0,
@@ -194,7 +166,8 @@ static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d)
static void tc3589x_gpio_irq_mask(struct irq_data *d)
{
- struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);
int offset = d->hwirq;
int regoffset = offset / 8;
int mask = 1 << (offset % 8);
@@ -204,7 +177,8 @@ static void tc3589x_gpio_irq_mask(struct irq_data *d)
static void tc3589x_gpio_irq_unmask(struct irq_data *d)
{
- struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);
int offset = d->hwirq;
int regoffset = offset / 8;
int mask = 1 << (offset % 8);
@@ -242,7 +216,8 @@ static irqreturn_t tc3589x_gpio_irq(int irq, void *dev)
while (stat) {
int bit = __ffs(stat);
int line = i * 8 + bit;
- int irq = tc3589x_gpio_irq_get_irq(tc3589x_gpio, line);
+ int irq = irq_find_mapping(tc3589x_gpio->chip.irqdomain,
+ line);
handle_nested_irq(irq);
stat &= ~(1 << bit);
@@ -254,61 +229,6 @@ static irqreturn_t tc3589x_gpio_irq(int irq, void *dev)
return IRQ_HANDLED;
}
-static int tc3589x_gpio_irq_map(struct irq_domain *d, unsigned int irq,
- irq_hw_number_t hwirq)
-{
- struct tc3589x *tc3589x_gpio = d->host_data;
-
- irq_set_chip_data(irq, tc3589x_gpio);
- irq_set_chip_and_handler(irq, &tc3589x_gpio_irq_chip,
- handle_simple_irq);
- irq_set_nested_thread(irq, 1);
-#ifdef CONFIG_ARM
- set_irq_flags(irq, IRQF_VALID);
-#else
- irq_set_noprobe(irq);
-#endif
-
- return 0;
-}
-
-static void tc3589x_gpio_irq_unmap(struct irq_domain *d, unsigned int irq)
-{
-#ifdef CONFIG_ARM
- set_irq_flags(irq, 0);
-#endif
- irq_set_chip_and_handler(irq, NULL, NULL);
- irq_set_chip_data(irq, NULL);
-}
-
-static struct irq_domain_ops tc3589x_irq_ops = {
- .map = tc3589x_gpio_irq_map,
- .unmap = tc3589x_gpio_irq_unmap,
- .xlate = irq_domain_xlate_twocell,
-};
-
-static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio,
- struct device_node *np)
-{
- int base = tc3589x_gpio->irq_base;
-
- /*
- * If this results in a linear domain, irq_create_mapping() will
- * take care of allocating IRQ descriptors at runtime. When a base
- * is provided, the IRQ descriptors will be allocated when the
- * domain is instantiated.
- */
- tc3589x_gpio->domain = irq_domain_add_simple(np,
- tc3589x_gpio->chip.ngpio, base, &tc3589x_irq_ops,
- tc3589x_gpio);
- if (!tc3589x_gpio->domain) {
- dev_err(tc3589x_gpio->dev, "Failed to create irqdomain\n");
- return -ENOSYS;
- }
-
- return 0;
-}
-
static int tc3589x_gpio_probe(struct platform_device *pdev)
{
struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent);
@@ -329,7 +249,8 @@ static int tc3589x_gpio_probe(struct platform_device *pdev)
if (irq < 0)
return irq;
- tc3589x_gpio = kzalloc(sizeof(struct tc3589x_gpio), GFP_KERNEL);
+ tc3589x_gpio = devm_kzalloc(&pdev->dev, sizeof(struct tc3589x_gpio),
+ GFP_KERNEL);
if (!tc3589x_gpio)
return -ENOMEM;
@@ -347,30 +268,36 @@ static int tc3589x_gpio_probe(struct platform_device *pdev)
tc3589x_gpio->chip.of_node = np;
#endif
- tc3589x_gpio->irq_base = tc3589x->irq_base ?
- tc3589x->irq_base + TC3589x_INT_GPIO(0) : 0;
-
/* Bring the GPIO module out of reset */
ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL,
TC3589x_RSTCTRL_GPIRST, 0);
if (ret < 0)
- goto out_free;
-
- ret = tc3589x_gpio_irq_init(tc3589x_gpio, np);
- if (ret)
- goto out_free;
+ return ret;
- ret = request_threaded_irq(irq, NULL, tc3589x_gpio_irq, IRQF_ONESHOT,
- "tc3589x-gpio", tc3589x_gpio);
+ ret = devm_request_threaded_irq(&pdev->dev,
+ irq, NULL, tc3589x_gpio_irq,
+ IRQF_ONESHOT, "tc3589x-gpio",
+ tc3589x_gpio);
if (ret) {
dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
- goto out_free;
+ return ret;
}
ret = gpiochip_add(&tc3589x_gpio->chip);
if (ret) {
dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret);
- goto out_freeirq;
+ return ret;
+ }
+
+ ret = gpiochip_irqchip_add(&tc3589x_gpio->chip,
+ &tc3589x_gpio_irq_chip,
+ 0,
+ handle_simple_irq,
+ IRQ_TYPE_NONE);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "could not connect irqchip to gpiochip\n");
+ return ret;
}
if (pdata && pdata->setup)
@@ -379,12 +306,6 @@ static int tc3589x_gpio_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, tc3589x_gpio);
return 0;
-
-out_freeirq:
- free_irq(irq, tc3589x_gpio);
-out_free:
- kfree(tc3589x_gpio);
- return ret;
}
static int tc3589x_gpio_remove(struct platform_device *pdev)
@@ -392,7 +313,6 @@ static int tc3589x_gpio_remove(struct platform_device *pdev)
struct tc3589x_gpio *tc3589x_gpio = platform_get_drvdata(pdev);
struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
struct tc3589x_gpio_platform_data *pdata = tc3589x->pdata->gpio;
- int irq = platform_get_irq(pdev, 0);
int ret;
if (pdata && pdata->remove)
@@ -405,10 +325,6 @@ static int tc3589x_gpio_remove(struct platform_device *pdev)
return ret;
}
- free_irq(irq, tc3589x_gpio);
-
- kfree(tc3589x_gpio);
-
return 0;
}
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
index 2b49f878b56c..4e8fb8261a87 100644
--- a/drivers/gpio/gpio-tegra.c
+++ b/drivers/gpio/gpio-tegra.c
@@ -408,7 +408,7 @@ static struct tegra_gpio_soc_config tegra30_gpio_config = {
.upper_offset = 0x80,
};
-static struct of_device_id tegra_gpio_of_match[] = {
+static const struct of_device_id tegra_gpio_of_match[] = {
{ .compatible = "nvidia,tegra30-gpio", .data = &tegra30_gpio_config },
{ .compatible = "nvidia,tegra20-gpio", .data = &tegra20_gpio_config },
{ },
@@ -458,10 +458,8 @@ static int tegra_gpio_probe(struct platform_device *pdev)
tegra_gpio_banks = devm_kzalloc(&pdev->dev,
tegra_gpio_bank_count * sizeof(*tegra_gpio_banks),
GFP_KERNEL);
- if (!tegra_gpio_banks) {
- dev_err(&pdev->dev, "Couldn't allocate bank structure\n");
+ if (!tegra_gpio_banks)
return -ENODEV;
- }
irq_domain = irq_domain_add_linear(pdev->dev.of_node,
tegra_gpio_chip.ngpio,
diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c
index f9a8fbde108e..efc7c129016d 100644
--- a/drivers/gpio/gpio-timberdale.c
+++ b/drivers/gpio/gpio-timberdale.c
@@ -224,6 +224,7 @@ static struct irq_chip timbgpio_irqchip = {
static int timbgpio_probe(struct platform_device *pdev)
{
int err, i;
+ struct device *dev = &pdev->dev;
struct gpio_chip *gc;
struct timbgpio *tgpio;
struct resource *iomem;
@@ -231,35 +232,35 @@ static int timbgpio_probe(struct platform_device *pdev)
int irq = platform_get_irq(pdev, 0);
if (!pdata || pdata->nr_pins > 32) {
- err = -EINVAL;
- goto err_mem;
+ dev_err(dev, "Invalid platform data\n");
+ return -EINVAL;
}
iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!iomem) {
- err = -EINVAL;
- goto err_mem;
+ dev_err(dev, "Unable to get resource\n");
+ return -EINVAL;
}
- tgpio = kzalloc(sizeof(*tgpio), GFP_KERNEL);
+ tgpio = devm_kzalloc(dev, sizeof(struct timbgpio), GFP_KERNEL);
if (!tgpio) {
- err = -EINVAL;
- goto err_mem;
+ dev_err(dev, "Memory alloc failed\n");
+ return -EINVAL;
}
tgpio->irq_base = pdata->irq_base;
spin_lock_init(&tgpio->lock);
- if (!request_mem_region(iomem->start, resource_size(iomem),
- DRIVER_NAME)) {
- err = -EBUSY;
- goto err_request;
+ if (!devm_request_mem_region(dev, iomem->start, resource_size(iomem),
+ DRIVER_NAME)) {
+ dev_err(dev, "Region already claimed\n");
+ return -EBUSY;
}
- tgpio->membase = ioremap(iomem->start, resource_size(iomem));
+ tgpio->membase = devm_ioremap(dev, iomem->start, resource_size(iomem));
if (!tgpio->membase) {
- err = -ENOMEM;
- goto err_ioremap;
+ dev_err(dev, "Cannot ioremap\n");
+ return -ENOMEM;
}
gc = &tgpio->gpio;
@@ -279,7 +280,7 @@ static int timbgpio_probe(struct platform_device *pdev)
err = gpiochip_add(gc);
if (err)
- goto err_chipadd;
+ return err;
platform_set_drvdata(pdev, tgpio);
@@ -302,17 +303,6 @@ static int timbgpio_probe(struct platform_device *pdev)
irq_set_chained_handler(irq, timbgpio_irq);
return 0;
-
-err_chipadd:
- iounmap(tgpio->membase);
-err_ioremap:
- release_mem_region(iomem->start, resource_size(iomem));
-err_request:
- kfree(tgpio);
-err_mem:
- printk(KERN_ERR DRIVER_NAME": Failed to register GPIOs: %d\n", err);
-
- return err;
}
static int timbgpio_remove(struct platform_device *pdev)
@@ -320,7 +310,6 @@ static int timbgpio_remove(struct platform_device *pdev)
int err;
struct timbgpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct timbgpio *tgpio = platform_get_drvdata(pdev);
- struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
int irq = platform_get_irq(pdev, 0);
if (irq >= 0 && tgpio->irq_base > 0) {
@@ -338,10 +327,6 @@ static int timbgpio_remove(struct platform_device *pdev)
if (err)
printk(KERN_ERR DRIVER_NAME": failed to remove gpio_chip\n");
- iounmap(tgpio->membase);
- release_mem_region(iomem->start, resource_size(iomem));
- kfree(tgpio);
-
return 0;
}
diff --git a/drivers/gpio/gpio-tps6586x.c b/drivers/gpio/gpio-tps6586x.c
index 8994dfa13491..a69fbea41253 100644
--- a/drivers/gpio/gpio-tps6586x.c
+++ b/drivers/gpio/gpio-tps6586x.c
@@ -97,10 +97,8 @@ static int tps6586x_gpio_probe(struct platform_device *pdev)
pdata = dev_get_platdata(pdev->dev.parent);
tps6586x_gpio = devm_kzalloc(&pdev->dev,
sizeof(*tps6586x_gpio), GFP_KERNEL);
- if (!tps6586x_gpio) {
- dev_err(&pdev->dev, "Could not allocate tps6586x_gpio\n");
+ if (!tps6586x_gpio)
return -ENOMEM;
- }
tps6586x_gpio->parent = pdev->dev.parent;
diff --git a/drivers/gpio/gpio-tps65910.c b/drivers/gpio/gpio-tps65910.c
index b6e818e68007..e2f8cda235ea 100644
--- a/drivers/gpio/gpio-tps65910.c
+++ b/drivers/gpio/gpio-tps65910.c
@@ -123,10 +123,8 @@ static int tps65910_gpio_probe(struct platform_device *pdev)
tps65910_gpio = devm_kzalloc(&pdev->dev,
sizeof(*tps65910_gpio), GFP_KERNEL);
- if (!tps65910_gpio) {
- dev_err(&pdev->dev, "Could not allocate tps65910_gpio\n");
+ if (!tps65910_gpio)
return -ENOMEM;
- }
tps65910_gpio->tps65910 = tps65910;
diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c
index 792a05ad4649..12481867daf1 100644
--- a/drivers/gpio/gpio-xilinx.c
+++ b/drivers/gpio/gpio-xilinx.c
@@ -289,7 +289,7 @@ static int xgpio_of_probe(struct device_node *np)
return 0;
}
-static struct of_device_id xgpio_of_match[] = {
+static const struct of_device_id xgpio_of_match[] = {
{ .compatible = "xlnx,xps-gpio-1.00.a", },
{ /* end of list */ },
};
diff --git a/drivers/gpio/gpio-zevio.c b/drivers/gpio/gpio-zevio.c
index 9bf5034b6cdb..54e54e4cc6c4 100644
--- a/drivers/gpio/gpio-zevio.c
+++ b/drivers/gpio/gpio-zevio.c
@@ -81,9 +81,15 @@ static inline void zevio_gpio_port_set(struct zevio_gpio *c, unsigned pin,
static int zevio_gpio_get(struct gpio_chip *chip, unsigned pin)
{
struct zevio_gpio *controller = to_zevio_gpio(chip);
+ u32 val, dir;
- /* Only reading allowed, so no spinlock needed */
- u32 val = zevio_gpio_port_get(controller, pin, ZEVIO_GPIO_INPUT);
+ spin_lock(&controller->lock);
+ dir = zevio_gpio_port_get(controller, pin, ZEVIO_GPIO_DIRECTION);
+ if (dir & BIT(ZEVIO_GPIO_BIT(pin)))
+ val = zevio_gpio_port_get(controller, pin, ZEVIO_GPIO_INPUT);
+ else
+ val = zevio_gpio_port_get(controller, pin, ZEVIO_GPIO_OUTPUT);
+ spin_unlock(&controller->lock);
return (val >> ZEVIO_GPIO_BIT(pin)) & 0x1;
}
@@ -172,10 +178,8 @@ static int zevio_gpio_probe(struct platform_device *pdev)
int status, i;
controller = devm_kzalloc(&pdev->dev, sizeof(*controller), GFP_KERNEL);
- if (!controller) {
- dev_err(&pdev->dev, "not enough free memory\n");
+ if (!controller)
return -ENOMEM;
- }
/* Copy our reference */
controller->chip.gc = zevio_gpio_chip;
@@ -198,7 +202,7 @@ static int zevio_gpio_probe(struct platform_device *pdev)
return 0;
}
-static struct of_device_id zevio_gpio_of_match[] = {
+static const struct of_device_id zevio_gpio_of_match[] = {
{ .compatible = "lsi,zevio-gpio", },
{ },
};
@@ -209,7 +213,7 @@ static struct platform_driver zevio_gpio_driver = {
.driver = {
.name = "gpio-zevio",
.owner = THIS_MODULE,
- .of_match_table = of_match_ptr(zevio_gpio_of_match),
+ .of_match_table = zevio_gpio_of_match,
},
.probe = zevio_gpio_probe,
};
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index bf0f8b476696..4a987917c186 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -233,7 +233,7 @@ static void acpi_gpiochip_request_interrupts(struct acpi_gpio_chip *acpi_gpio)
{
struct gpio_chip *chip = acpi_gpio->chip;
- if (!chip->dev || !chip->to_irq)
+ if (!chip->to_irq)
return;
INIT_LIST_HEAD(&acpi_gpio->events);
@@ -253,7 +253,7 @@ static void acpi_gpiochip_free_interrupts(struct acpi_gpio_chip *acpi_gpio)
struct acpi_gpio_event *event, *ep;
struct gpio_chip *chip = acpi_gpio->chip;
- if (!chip->dev || !chip->to_irq)
+ if (!chip->to_irq)
return;
list_for_each_entry_safe_reverse(event, ep, &acpi_gpio->events, node) {
@@ -449,9 +449,10 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
mutex_unlock(&achip->conn_lock);
if (function == ACPI_WRITE)
- gpiod_set_raw_value(desc, !!((1 << i) & *value));
+ gpiod_set_raw_value_cansleep(desc,
+ !!((1 << i) & *value));
else
- *value |= gpiod_get_raw_value(desc) << i;
+ *value |= (u64)gpiod_get_raw_value_cansleep(desc) << i;
}
out:
@@ -501,6 +502,9 @@ void acpi_gpiochip_add(struct gpio_chip *chip)
acpi_handle handle;
acpi_status status;
+ if (!chip || !chip->dev)
+ return;
+
handle = ACPI_HANDLE(chip->dev);
if (!handle)
return;
@@ -531,6 +535,9 @@ void acpi_gpiochip_remove(struct gpio_chip *chip)
acpi_handle handle;
acpi_status status;
+ if (!chip || !chip->dev)
+ return;
+
handle = ACPI_HANDLE(chip->dev);
if (!handle)
return;
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index 2024d45e5503..af7e25c9a9ae 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -48,7 +48,7 @@ static int of_gpiochip_find_and_xlate(struct gpio_chip *gc, void *data)
if (ret < 0)
return false;
- gg_data->out_gpio = gpio_to_desc(ret + gc->base);
+ gg_data->out_gpio = gpiochip_get_desc(gc, ret);
return true;
}
@@ -96,6 +96,20 @@ struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
}
EXPORT_SYMBOL(of_get_named_gpiod_flags);
+int of_get_named_gpio_flags(struct device_node *np, const char *list_name,
+ int index, enum of_gpio_flags *flags)
+{
+ struct gpio_desc *desc;
+
+ desc = of_get_named_gpiod_flags(np, list_name, index, flags);
+
+ if (IS_ERR(desc))
+ return PTR_ERR(desc);
+ else
+ return desc_to_gpio(desc);
+}
+EXPORT_SYMBOL(of_get_named_gpio_flags);
+
/**
* of_gpio_simple_xlate - translate gpio_spec to the GPIO number and flags
* @gc: pointer to the gpio_chip structure
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 761013f8b82f..d9c9cb4665db 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1363,6 +1363,11 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
int parent_irq,
irq_flow_handler_t parent_handler)
{
+ if (gpiochip->can_sleep) {
+ chip_err(gpiochip, "you cannot have chained interrupts on a chip that may sleep\n");
+ return;
+ }
+
irq_set_chained_handler(parent_irq, parent_handler);
/*
* The parent irqchip is already using the chip_data for this
@@ -1372,6 +1377,12 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
}
EXPORT_SYMBOL_GPL(gpiochip_set_chained_irqchip);
+/*
+ * This lock class tells lockdep that GPIO irqs are in a different
+ * category than their parents, so it won't report false recursion.
+ */
+static struct lock_class_key gpiochip_irq_lock_class;
+
/**
* gpiochip_irq_map() - maps an IRQ into a GPIO irqchip
* @d: the irqdomain used by this irqchip
@@ -1387,23 +1398,36 @@ static int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
{
struct gpio_chip *chip = d->host_data;
- irq_set_chip_and_handler(irq, chip->irqchip, chip->irq_handler);
irq_set_chip_data(irq, chip);
+ irq_set_lockdep_class(irq, &gpiochip_irq_lock_class);
+ irq_set_chip_and_handler(irq, chip->irqchip, chip->irq_handler);
+ /* Chips that can sleep need nested thread handlers */
+ if (chip->can_sleep)
+ irq_set_nested_thread(irq, 1);
#ifdef CONFIG_ARM
set_irq_flags(irq, IRQF_VALID);
#else
irq_set_noprobe(irq);
#endif
- irq_set_irq_type(irq, chip->irq_default_type);
+ /*
+ * No set-up of the hardware will happen if IRQ_TYPE_NONE
+ * is passed as default type.
+ */
+ if (chip->irq_default_type != IRQ_TYPE_NONE)
+ irq_set_irq_type(irq, chip->irq_default_type);
return 0;
}
static void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq)
{
+ struct gpio_chip *chip = d->host_data;
+
#ifdef CONFIG_ARM
set_irq_flags(irq, 0);
#endif
+ if (chip->can_sleep)
+ irq_set_nested_thread(irq, 0);
irq_set_chip_and_handler(irq, NULL, NULL);
irq_set_chip_data(irq, NULL);
}
@@ -1471,7 +1495,8 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
* @first_irq: if not dynamically assigned, the base (first) IRQ to
* allocate gpiochip irqs from
* @handler: the irq handler to use (often a predefined irq core function)
- * @type: the default type for IRQs on this irqchip
+ * @type: the default type for IRQs on this irqchip, pass IRQ_TYPE_NONE
+ * to have the core avoid setting up any default type in the hardware.
*
* This function closely associates a certain irqchip with a certain
* gpiochip, providing an irq domain to translate the local IRQs to
@@ -2571,22 +2596,27 @@ void gpiod_add_lookup_table(struct gpiod_lookup_table *table)
mutex_unlock(&gpio_lookup_lock);
}
-#ifdef CONFIG_OF
static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
unsigned int idx,
enum gpio_lookup_flags *flags)
{
+ static const char *suffixes[] = { "gpios", "gpio" };
char prop_name[32]; /* 32 is max size of property name */
enum of_gpio_flags of_flags;
struct gpio_desc *desc;
+ unsigned int i;
- if (con_id)
- snprintf(prop_name, 32, "%s-gpios", con_id);
- else
- snprintf(prop_name, 32, "gpios");
+ for (i = 0; i < ARRAY_SIZE(suffixes); i++) {
+ if (con_id)
+ snprintf(prop_name, 32, "%s-%s", con_id, suffixes[i]);
+ else
+ snprintf(prop_name, 32, "%s", suffixes[i]);
- desc = of_get_named_gpiod_flags(dev->of_node, prop_name, idx,
- &of_flags);
+ desc = of_get_named_gpiod_flags(dev->of_node, prop_name, idx,
+ &of_flags);
+ if (!IS_ERR(desc))
+ break;
+ }
if (IS_ERR(desc))
return desc;
@@ -2596,14 +2626,6 @@ static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
return desc;
}
-#else
-static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
- unsigned int idx,
- enum gpio_lookup_flags *flags)
-{
- return ERR_PTR(-ENODEV);
-}
-#endif
static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id,
unsigned int idx,
@@ -2701,7 +2723,7 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id,
}
/**
- * gpio_get - obtain a GPIO for a given GPIO function
+ * gpiod_get - obtain a GPIO for a given GPIO function
* @dev: GPIO consumer, can be NULL for system-global GPIOs
* @con_id: function within the GPIO consumer
*
@@ -2716,6 +2738,22 @@ struct gpio_desc *__must_check gpiod_get(struct device *dev, const char *con_id)
EXPORT_SYMBOL_GPL(gpiod_get);
/**
+ * gpiod_get_optional - obtain an optional GPIO for a given GPIO function
+ * @dev: GPIO consumer, can be NULL for system-global GPIOs
+ * @con_id: function within the GPIO consumer
+ *
+ * This is equivalent to gpiod_get(), except that when no GPIO was assigned to
+ * the requested function it will return NULL. This is convenient for drivers
+ * that need to handle optional GPIOs.
+ */
+struct gpio_desc *__must_check gpiod_get_optional(struct device *dev,
+ const char *con_id)
+{
+ return gpiod_get_index_optional(dev, con_id, 0);
+}
+EXPORT_SYMBOL_GPL(gpiod_get_optional);
+
+/**
* gpiod_get_index - obtain a GPIO from a multi-index GPIO function
* @dev: GPIO consumer, can be NULL for system-global GPIOs
* @con_id: function within the GPIO consumer
@@ -2778,6 +2816,33 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
EXPORT_SYMBOL_GPL(gpiod_get_index);
/**
+ * gpiod_get_index_optional - obtain an optional GPIO from a multi-index GPIO
+ * function
+ * @dev: GPIO consumer, can be NULL for system-global GPIOs
+ * @con_id: function within the GPIO consumer
+ * @index: index of the GPIO to obtain in the consumer
+ *
+ * This is equivalent to gpiod_get_index(), except that when no GPIO with the
+ * specified index was assigned to the requested function it will return NULL.
+ * This is convenient for drivers that need to handle optional GPIOs.
+ */
+struct gpio_desc *__must_check gpiod_get_index_optional(struct device *dev,
+ const char *con_id,
+ unsigned int index)
+{
+ struct gpio_desc *desc;
+
+ desc = gpiod_get_index(dev, con_id, index);
+ if (IS_ERR(desc)) {
+ if (PTR_ERR(desc) == -ENOENT)
+ return NULL;
+ }
+
+ return desc;
+}
+EXPORT_SYMBOL_GPL(gpiod_get_index_optional);
+
+/**
* gpiod_put - dispose of a GPIO descriptor
* @desc: GPIO descriptor to dispose of
*
diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
index cf092941a9fd..1a4103dd38df 100644
--- a/drivers/gpio/gpiolib.h
+++ b/drivers/gpio/gpiolib.h
@@ -15,6 +15,8 @@
#include <linux/err.h>
#include <linux/device.h>
+enum of_gpio_flags;
+
/**
* struct acpi_gpio_info - ACPI GPIO specific information
* @gpioint: if %true this GPIO is of type GpioInt otherwise type is GpioIo
@@ -46,4 +48,7 @@ acpi_get_gpiod_by_index(struct device *dev, int index,
int gpiochip_request_own_desc(struct gpio_desc *desc, const char *label);
void gpiochip_free_own_desc(struct gpio_desc *desc);
+struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
+ const char *list_name, int index, enum of_gpio_flags *flags);
+
#endif /* GPIOLIB_H */
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 9d25dbbe6771..48e38ba22783 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -23,7 +23,7 @@ drm-$(CONFIG_DRM_PANEL) += drm_panel.o
drm-usb-y := drm_usb.o
-drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o
+drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o
drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
drm_kms_helper-$(CONFIG_DRM_KMS_FB_HELPER) += drm_fb_helper.o
drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o
diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c
index 977cfb35837a..635f6ffc27c2 100644
--- a/drivers/gpu/drm/ast/ast_post.c
+++ b/drivers/gpu/drm/ast/ast_post.c
@@ -572,7 +572,7 @@ static u32 cbr_scan2(struct ast_private *ast)
for (loop = 0; loop < CBR_PASSNUM2; loop++) {
if ((data = cbr_test2(ast)) != 0) {
data2 &= data;
- if (!data)
+ if (!data2)
return 0;
break;
}
diff --git a/drivers/gpu/drm/bochs/bochs.h b/drivers/gpu/drm/bochs/bochs.h
index 741965c001a6..7eb52dd44b01 100644
--- a/drivers/gpu/drm/bochs/bochs.h
+++ b/drivers/gpu/drm/bochs/bochs.h
@@ -1,5 +1,6 @@
#include <linux/io.h>
#include <linux/fb.h>
+#include <linux/console.h>
#include <drm/drmP.h>
#include <drm/drm_crtc.h>
@@ -87,8 +88,6 @@ struct bochs_device {
struct bochs_framebuffer gfb;
struct drm_fb_helper helper;
int size;
- int x1, y1, x2, y2; /* dirty rect */
- spinlock_t dirty_lock;
bool initialized;
} fb;
};
diff --git a/drivers/gpu/drm/bochs/bochs_drv.c b/drivers/gpu/drm/bochs/bochs_drv.c
index 395bba261c9a..9c13df29fd20 100644
--- a/drivers/gpu/drm/bochs/bochs_drv.c
+++ b/drivers/gpu/drm/bochs/bochs_drv.c
@@ -95,6 +95,49 @@ static struct drm_driver bochs_driver = {
};
/* ---------------------------------------------------------------------- */
+/* pm interface */
+
+static int bochs_pm_suspend(struct device *dev)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct drm_device *drm_dev = pci_get_drvdata(pdev);
+ struct bochs_device *bochs = drm_dev->dev_private;
+
+ drm_kms_helper_poll_disable(drm_dev);
+
+ if (bochs->fb.initialized) {
+ console_lock();
+ fb_set_suspend(bochs->fb.helper.fbdev, 1);
+ console_unlock();
+ }
+
+ return 0;
+}
+
+static int bochs_pm_resume(struct device *dev)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct drm_device *drm_dev = pci_get_drvdata(pdev);
+ struct bochs_device *bochs = drm_dev->dev_private;
+
+ drm_helper_resume_force_mode(drm_dev);
+
+ if (bochs->fb.initialized) {
+ console_lock();
+ fb_set_suspend(bochs->fb.helper.fbdev, 0);
+ console_unlock();
+ }
+
+ drm_kms_helper_poll_enable(drm_dev);
+ return 0;
+}
+
+static const struct dev_pm_ops bochs_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(bochs_pm_suspend,
+ bochs_pm_resume)
+};
+
+/* ---------------------------------------------------------------------- */
/* pci interface */
static int bochs_kick_out_firmware_fb(struct pci_dev *pdev)
@@ -155,6 +198,7 @@ static struct pci_driver bochs_pci_driver = {
.id_table = bochs_pci_tbl,
.probe = bochs_pci_probe,
.remove = bochs_pci_remove,
+ .driver.pm = &bochs_pm_ops,
};
/* ---------------------------------------------------------------------- */
diff --git a/drivers/gpu/drm/bochs/bochs_fbdev.c b/drivers/gpu/drm/bochs/bochs_fbdev.c
index 4da5206b7cc9..561b84474122 100644
--- a/drivers/gpu/drm/bochs/bochs_fbdev.c
+++ b/drivers/gpu/drm/bochs/bochs_fbdev.c
@@ -190,7 +190,6 @@ int bochs_fbdev_init(struct bochs_device *bochs)
int ret;
bochs->fb.helper.funcs = &bochs_fb_helper_funcs;
- spin_lock_init(&bochs->fb.dirty_lock);
ret = drm_fb_helper_init(bochs->dev, &bochs->fb.helper,
1, 1);
diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c
index 953fc8aea69c..08ce520f61a5 100644
--- a/drivers/gpu/drm/cirrus/cirrus_drv.c
+++ b/drivers/gpu/drm/cirrus/cirrus_drv.c
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/console.h>
#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
#include "cirrus_drv.h"
@@ -75,6 +76,41 @@ static void cirrus_pci_remove(struct pci_dev *pdev)
drm_put_dev(dev);
}
+static int cirrus_pm_suspend(struct device *dev)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct drm_device *drm_dev = pci_get_drvdata(pdev);
+ struct cirrus_device *cdev = drm_dev->dev_private;
+
+ drm_kms_helper_poll_disable(drm_dev);
+
+ if (cdev->mode_info.gfbdev) {
+ console_lock();
+ fb_set_suspend(cdev->mode_info.gfbdev->helper.fbdev, 1);
+ console_unlock();
+ }
+
+ return 0;
+}
+
+static int cirrus_pm_resume(struct device *dev)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct drm_device *drm_dev = pci_get_drvdata(pdev);
+ struct cirrus_device *cdev = drm_dev->dev_private;
+
+ drm_helper_resume_force_mode(drm_dev);
+
+ if (cdev->mode_info.gfbdev) {
+ console_lock();
+ fb_set_suspend(cdev->mode_info.gfbdev->helper.fbdev, 0);
+ console_unlock();
+ }
+
+ drm_kms_helper_poll_enable(drm_dev);
+ return 0;
+}
+
static const struct file_operations cirrus_driver_fops = {
.owner = THIS_MODULE,
.open = drm_open,
@@ -103,11 +139,17 @@ static struct drm_driver driver = {
.dumb_destroy = drm_gem_dumb_destroy,
};
+static const struct dev_pm_ops cirrus_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(cirrus_pm_suspend,
+ cirrus_pm_resume)
+};
+
static struct pci_driver cirrus_pci_driver = {
.name = DRIVER_NAME,
.id_table = pciidlist,
.probe = cirrus_pci_probe,
.remove = cirrus_pci_remove,
+ .driver.pm = &cirrus_pm_ops,
};
static int __init cirrus_init(void)
diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c
index 2d64aea83df2..f59433b7610c 100644
--- a/drivers/gpu/drm/cirrus/cirrus_mode.c
+++ b/drivers/gpu/drm/cirrus/cirrus_mode.c
@@ -308,6 +308,9 @@ static int cirrus_crtc_mode_set(struct drm_crtc *crtc,
WREG_HDR(hdr);
cirrus_crtc_do_set_base(crtc, old_fb, x, y, 0);
+
+ /* Unblank (needed on S3 resume, vgabios doesn't do it then) */
+ outb(0x20, 0x3c0);
return 0;
}
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index c43825e8f5c1..df281b54db01 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -72,147 +72,6 @@ void drm_helper_move_panel_connectors_to_head(struct drm_device *dev)
}
EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head);
-static bool drm_kms_helper_poll = true;
-module_param_named(poll, drm_kms_helper_poll, bool, 0600);
-
-static void drm_mode_validate_flag(struct drm_connector *connector,
- int flags)
-{
- struct drm_display_mode *mode;
-
- if (flags == (DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_INTERLACE |
- DRM_MODE_FLAG_3D_MASK))
- return;
-
- list_for_each_entry(mode, &connector->modes, head) {
- if ((mode->flags & DRM_MODE_FLAG_INTERLACE) &&
- !(flags & DRM_MODE_FLAG_INTERLACE))
- mode->status = MODE_NO_INTERLACE;
- if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) &&
- !(flags & DRM_MODE_FLAG_DBLSCAN))
- mode->status = MODE_NO_DBLESCAN;
- if ((mode->flags & DRM_MODE_FLAG_3D_MASK) &&
- !(flags & DRM_MODE_FLAG_3D_MASK))
- mode->status = MODE_NO_STEREO;
- }
-
- return;
-}
-
-/**
- * drm_helper_probe_single_connector_modes - get complete set of display modes
- * @connector: connector to probe
- * @maxX: max width for modes
- * @maxY: max height for modes
- *
- * Based on the helper callbacks implemented by @connector try to detect all
- * valid modes. Modes will first be added to the connector's probed_modes list,
- * then culled (based on validity and the @maxX, @maxY parameters) and put into
- * the normal modes list.
- *
- * Intended to be use as a generic implementation of the ->fill_modes()
- * @connector vfunc for drivers that use the crtc helpers for output mode
- * filtering and detection.
- *
- * Returns:
- * The number of modes found on @connector.
- */
-int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
- uint32_t maxX, uint32_t maxY)
-{
- struct drm_device *dev = connector->dev;
- struct drm_display_mode *mode;
- struct drm_connector_helper_funcs *connector_funcs =
- connector->helper_private;
- int count = 0;
- int mode_flags = 0;
- bool verbose_prune = true;
-
- WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
-
- DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id,
- drm_get_connector_name(connector));
- /* set all modes to the unverified state */
- list_for_each_entry(mode, &connector->modes, head)
- mode->status = MODE_UNVERIFIED;
-
- if (connector->force) {
- if (connector->force == DRM_FORCE_ON)
- connector->status = connector_status_connected;
- else
- connector->status = connector_status_disconnected;
- if (connector->funcs->force)
- connector->funcs->force(connector);
- } else {
- connector->status = connector->funcs->detect(connector, true);
- }
-
- /* Re-enable polling in case the global poll config changed. */
- if (drm_kms_helper_poll != dev->mode_config.poll_running)
- drm_kms_helper_poll_enable(dev);
-
- dev->mode_config.poll_running = drm_kms_helper_poll;
-
- if (connector->status == connector_status_disconnected) {
- DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n",
- connector->base.id, drm_get_connector_name(connector));
- drm_mode_connector_update_edid_property(connector, NULL);
- verbose_prune = false;
- goto prune;
- }
-
-#ifdef CONFIG_DRM_LOAD_EDID_FIRMWARE
- count = drm_load_edid_firmware(connector);
- if (count == 0)
-#endif
- count = (*connector_funcs->get_modes)(connector);
-
- if (count == 0 && connector->status == connector_status_connected)
- count = drm_add_modes_noedid(connector, 1024, 768);
- if (count == 0)
- goto prune;
-
- drm_mode_connector_list_update(connector);
-
- if (maxX && maxY)
- drm_mode_validate_size(dev, &connector->modes, maxX, maxY);
-
- if (connector->interlace_allowed)
- mode_flags |= DRM_MODE_FLAG_INTERLACE;
- if (connector->doublescan_allowed)
- mode_flags |= DRM_MODE_FLAG_DBLSCAN;
- if (connector->stereo_allowed)
- mode_flags |= DRM_MODE_FLAG_3D_MASK;
- drm_mode_validate_flag(connector, mode_flags);
-
- list_for_each_entry(mode, &connector->modes, head) {
- if (mode->status == MODE_OK)
- mode->status = connector_funcs->mode_valid(connector,
- mode);
- }
-
-prune:
- drm_mode_prune_invalid(dev, &connector->modes, verbose_prune);
-
- if (list_empty(&connector->modes))
- return 0;
-
- list_for_each_entry(mode, &connector->modes, head)
- mode->vrefresh = drm_mode_vrefresh(mode);
-
- drm_mode_sort(&connector->modes);
-
- DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed modes :\n", connector->base.id,
- drm_get_connector_name(connector));
- list_for_each_entry(mode, &connector->modes, head) {
- drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
- drm_mode_debug_printmodeline(mode);
- }
-
- return count;
-}
-EXPORT_SYMBOL(drm_helper_probe_single_connector_modes);
-
/**
* drm_helper_encoder_in_use - check if a given encoder is in use
* @encoder: encoder to check
@@ -1020,232 +879,3 @@ void drm_helper_resume_force_mode(struct drm_device *dev)
drm_modeset_unlock_all(dev);
}
EXPORT_SYMBOL(drm_helper_resume_force_mode);
-
-/**
- * drm_kms_helper_hotplug_event - fire off KMS hotplug events
- * @dev: drm_device whose connector state changed
- *
- * This function fires off the uevent for userspace and also calls the
- * output_poll_changed function, which is most commonly used to inform the fbdev
- * emulation code and allow it to update the fbcon output configuration.
- *
- * Drivers should call this from their hotplug handling code when a change is
- * detected. Note that this function does not do any output detection of its
- * own, like drm_helper_hpd_irq_event() does - this is assumed to be done by the
- * driver already.
- *
- * This function must be called from process context with no mode
- * setting locks held.
- */
-void drm_kms_helper_hotplug_event(struct drm_device *dev)
-{
- /* send a uevent + call fbdev */
- drm_sysfs_hotplug_event(dev);
- if (dev->mode_config.funcs->output_poll_changed)
- dev->mode_config.funcs->output_poll_changed(dev);
-}
-EXPORT_SYMBOL(drm_kms_helper_hotplug_event);
-
-#define DRM_OUTPUT_POLL_PERIOD (10*HZ)
-static void output_poll_execute(struct work_struct *work)
-{
- struct delayed_work *delayed_work = to_delayed_work(work);
- struct drm_device *dev = container_of(delayed_work, struct drm_device, mode_config.output_poll_work);
- struct drm_connector *connector;
- enum drm_connector_status old_status;
- bool repoll = false, changed = false;
-
- if (!drm_kms_helper_poll)
- return;
-
- mutex_lock(&dev->mode_config.mutex);
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-
- /* Ignore forced connectors. */
- if (connector->force)
- continue;
-
- /* Ignore HPD capable connectors and connectors where we don't
- * want any hotplug detection at all for polling. */
- if (!connector->polled || connector->polled == DRM_CONNECTOR_POLL_HPD)
- continue;
-
- repoll = true;
-
- old_status = connector->status;
- /* if we are connected and don't want to poll for disconnect
- skip it */
- if (old_status == connector_status_connected &&
- !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT))
- continue;
-
- connector->status = connector->funcs->detect(connector, false);
- if (old_status != connector->status) {
- const char *old, *new;
-
- old = drm_get_connector_status_name(old_status);
- new = drm_get_connector_status_name(connector->status);
-
- DRM_DEBUG_KMS("[CONNECTOR:%d:%s] "
- "status updated from %s to %s\n",
- connector->base.id,
- drm_get_connector_name(connector),
- old, new);
-
- changed = true;
- }
- }
-
- mutex_unlock(&dev->mode_config.mutex);
-
- if (changed)
- drm_kms_helper_hotplug_event(dev);
-
- if (repoll)
- schedule_delayed_work(delayed_work, DRM_OUTPUT_POLL_PERIOD);
-}
-
-/**
- * drm_kms_helper_poll_disable - disable output polling
- * @dev: drm_device
- *
- * This function disables the output polling work.
- *
- * Drivers can call this helper from their device suspend implementation. It is
- * not an error to call this even when output polling isn't enabled or arlready
- * disabled.
- */
-void drm_kms_helper_poll_disable(struct drm_device *dev)
-{
- if (!dev->mode_config.poll_enabled)
- return;
- cancel_delayed_work_sync(&dev->mode_config.output_poll_work);
-}
-EXPORT_SYMBOL(drm_kms_helper_poll_disable);
-
-/**
- * drm_kms_helper_poll_enable - re-enable output polling.
- * @dev: drm_device
- *
- * This function re-enables the output polling work.
- *
- * Drivers can call this helper from their device resume implementation. It is
- * an error to call this when the output polling support has not yet been set
- * up.
- */
-void drm_kms_helper_poll_enable(struct drm_device *dev)
-{
- bool poll = false;
- struct drm_connector *connector;
-
- if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll)
- return;
-
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT |
- DRM_CONNECTOR_POLL_DISCONNECT))
- poll = true;
- }
-
- if (poll)
- schedule_delayed_work(&dev->mode_config.output_poll_work, DRM_OUTPUT_POLL_PERIOD);
-}
-EXPORT_SYMBOL(drm_kms_helper_poll_enable);
-
-/**
- * drm_kms_helper_poll_init - initialize and enable output polling
- * @dev: drm_device
- *
- * This function intializes and then also enables output polling support for
- * @dev. Drivers which do not have reliable hotplug support in hardware can use
- * this helper infrastructure to regularly poll such connectors for changes in
- * their connection state.
- *
- * Drivers can control which connectors are polled by setting the
- * DRM_CONNECTOR_POLL_CONNECT and DRM_CONNECTOR_POLL_DISCONNECT flags. On
- * connectors where probing live outputs can result in visual distortion drivers
- * should not set the DRM_CONNECTOR_POLL_DISCONNECT flag to avoid this.
- * Connectors which have no flag or only DRM_CONNECTOR_POLL_HPD set are
- * completely ignored by the polling logic.
- *
- * Note that a connector can be both polled and probed from the hotplug handler,
- * in case the hotplug interrupt is known to be unreliable.
- */
-void drm_kms_helper_poll_init(struct drm_device *dev)
-{
- INIT_DELAYED_WORK(&dev->mode_config.output_poll_work, output_poll_execute);
- dev->mode_config.poll_enabled = true;
-
- drm_kms_helper_poll_enable(dev);
-}
-EXPORT_SYMBOL(drm_kms_helper_poll_init);
-
-/**
- * drm_kms_helper_poll_fini - disable output polling and clean it up
- * @dev: drm_device
- */
-void drm_kms_helper_poll_fini(struct drm_device *dev)
-{
- drm_kms_helper_poll_disable(dev);
-}
-EXPORT_SYMBOL(drm_kms_helper_poll_fini);
-
-/**
- * drm_helper_hpd_irq_event - hotplug processing
- * @dev: drm_device
- *
- * Drivers can use this helper function to run a detect cycle on all connectors
- * which have the DRM_CONNECTOR_POLL_HPD flag set in their &polled member. All
- * other connectors are ignored, which is useful to avoid reprobing fixed
- * panels.
- *
- * This helper function is useful for drivers which can't or don't track hotplug
- * interrupts for each connector.
- *
- * Drivers which support hotplug interrupts for each connector individually and
- * which have a more fine-grained detect logic should bypass this code and
- * directly call drm_kms_helper_hotplug_event() in case the connector state
- * changed.
- *
- * This function must be called from process context with no mode
- * setting locks held.
- *
- * Note that a connector can be both polled and probed from the hotplug handler,
- * in case the hotplug interrupt is known to be unreliable.
- */
-bool drm_helper_hpd_irq_event(struct drm_device *dev)
-{
- struct drm_connector *connector;
- enum drm_connector_status old_status;
- bool changed = false;
-
- if (!dev->mode_config.poll_enabled)
- return false;
-
- mutex_lock(&dev->mode_config.mutex);
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-
- /* Only handle HPD capable connectors. */
- if (!(connector->polled & DRM_CONNECTOR_POLL_HPD))
- continue;
-
- old_status = connector->status;
-
- connector->status = connector->funcs->detect(connector, false);
- DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n",
- connector->base.id,
- drm_get_connector_name(connector),
- drm_get_connector_status_name(old_status),
- drm_get_connector_status_name(connector->status));
- if (old_status != connector->status)
- changed = true;
- }
-
- mutex_unlock(&dev->mode_config.mutex);
-
- if (changed)
- drm_kms_helper_hotplug_event(dev);
-
- return changed;
-}
-EXPORT_SYMBOL(drm_helper_hpd_irq_event);
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 27671489477d..4b6e6f3ba0a1 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -577,7 +577,9 @@ static u32 drm_dp_i2c_functionality(struct i2c_adapter *adapter)
/*
* Transfer a single I2C-over-AUX message and handle various error conditions,
- * retrying the transaction as appropriate.
+ * retrying the transaction as appropriate. It is assumed that the
+ * aux->transfer function does not modify anything in the msg other than the
+ * reply field.
*/
static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
{
@@ -665,11 +667,26 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
{
struct drm_dp_aux *aux = adapter->algo_data;
unsigned int i, j;
+ struct drm_dp_aux_msg msg;
+ int err = 0;
- for (i = 0; i < num; i++) {
- struct drm_dp_aux_msg msg;
- int err;
+ memset(&msg, 0, sizeof(msg));
+ for (i = 0; i < num; i++) {
+ msg.address = msgs[i].addr;
+ msg.request = (msgs[i].flags & I2C_M_RD) ?
+ DP_AUX_I2C_READ :
+ DP_AUX_I2C_WRITE;
+ msg.request |= DP_AUX_I2C_MOT;
+ /* Send a bare address packet to start the transaction.
+ * Zero sized messages specify an address only (bare
+ * address) transaction.
+ */
+ msg.buffer = NULL;
+ msg.size = 0;
+ err = drm_dp_i2c_do_msg(aux, &msg);
+ if (err < 0)
+ break;
/*
* Many hardware implementations support FIFOs larger than a
* single byte, but it has been empirically determined that
@@ -678,30 +695,28 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
* transferred byte-by-byte.
*/
for (j = 0; j < msgs[i].len; j++) {
- memset(&msg, 0, sizeof(msg));
- msg.address = msgs[i].addr;
-
- msg.request = (msgs[i].flags & I2C_M_RD) ?
- DP_AUX_I2C_READ :
- DP_AUX_I2C_WRITE;
-
- /*
- * All messages except the last one are middle-of-
- * transfer messages.
- */
- if ((i < num - 1) || (j < msgs[i].len - 1))
- msg.request |= DP_AUX_I2C_MOT;
-
msg.buffer = msgs[i].buf + j;
msg.size = 1;
err = drm_dp_i2c_do_msg(aux, &msg);
if (err < 0)
- return err;
+ break;
}
+ if (err < 0)
+ break;
}
+ if (err >= 0)
+ err = num;
+ /* Send a bare address packet to close out the transaction.
+ * Zero sized messages specify an address only (bare
+ * address) transaction.
+ */
+ msg.request &= ~DP_AUX_I2C_MOT;
+ msg.buffer = NULL;
+ msg.size = 0;
+ (void)drm_dp_i2c_do_msg(aux, &msg);
- return num;
+ return err;
}
static const struct i2c_algorithm drm_dp_i2c_algo = {
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
index 71e2d3fcd6ee..04a209e2b66d 100644
--- a/drivers/gpu/drm/drm_mm.c
+++ b/drivers/gpu/drm/drm_mm.c
@@ -207,8 +207,6 @@ int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node)
return 0;
}
- WARN(1, "no hole found for node 0x%lx + 0x%lx\n",
- node->start, node->size);
return -ENOSPC;
}
EXPORT_SYMBOL(drm_mm_reserve_node);
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
index e768d35ff22e..d2b1c03b3d71 100644
--- a/drivers/gpu/drm/drm_plane_helper.c
+++ b/drivers/gpu/drm/drm_plane_helper.c
@@ -203,9 +203,9 @@ EXPORT_SYMBOL(drm_primary_helper_update);
*
* Provides a default plane disable handler for primary planes. This is handler
* is called in response to a userspace SetPlane operation on the plane with a
- * NULL framebuffer parameter. We call the driver's modeset handler with a NULL
- * framebuffer to disable the CRTC if no other planes are currently enabled.
- * If other planes are still enabled on the same CRTC, we return -EBUSY.
+ * NULL framebuffer parameter. It unconditionally fails the disable call with
+ * -EINVAL the only way to disable the primary plane without driver support is
+ * to disable the entier CRTC. Which does not match the plane ->disable hook.
*
* Note that some hardware may be able to disable the primary plane without
* disabling the whole CRTC. Drivers for such hardware should provide their
@@ -214,34 +214,11 @@ EXPORT_SYMBOL(drm_primary_helper_update);
* disabled primary plane).
*
* RETURNS:
- * Zero on success, error code on failure
+ * Unconditionally returns -EINVAL.
*/
int drm_primary_helper_disable(struct drm_plane *plane)
{
- struct drm_plane *p;
- struct drm_mode_set set = {
- .crtc = plane->crtc,
- .fb = NULL,
- };
-
- if (plane->crtc == NULL || plane->fb == NULL)
- /* Already disabled */
- return 0;
-
- list_for_each_entry(p, &plane->dev->mode_config.plane_list, head)
- if (p != plane && p->fb) {
- DRM_DEBUG_KMS("Cannot disable primary plane while other planes are still active on CRTC.\n");
- return -EBUSY;
- }
-
- /*
- * N.B. We call set_config() directly here rather than
- * drm_mode_set_config_internal() since drm_mode_setplane() already
- * handles the basic refcounting and we don't need the special
- * cross-CRTC refcounting (no chance of stealing connectors from
- * other CRTC's with this update).
- */
- return plane->crtc->funcs->set_config(&set);
+ return -EINVAL;
}
EXPORT_SYMBOL(drm_primary_helper_disable);
diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
new file mode 100644
index 000000000000..e70f54d4a581
--- /dev/null
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -0,0 +1,426 @@
+/*
+ * Copyright (c) 2006-2008 Intel Corporation
+ * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
+ *
+ * DRM core CRTC related functions
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ *
+ * Authors:
+ * Keith Packard
+ * Eric Anholt <eric@anholt.net>
+ * Dave Airlie <airlied@linux.ie>
+ * Jesse Barnes <jesse.barnes@intel.com>
+ */
+
+#include <linux/export.h>
+#include <linux/moduleparam.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_edid.h>
+
+/**
+ * DOC: output probing helper overview
+ *
+ * This library provides some helper code for output probing. It provides an
+ * implementation of the core connector->fill_modes interface with
+ * drm_helper_probe_single_connector_modes.
+ *
+ * It also provides support for polling connectors with a work item and for
+ * generic hotplug interrupt handling where the driver doesn't or cannot keep
+ * track of a per-connector hpd interrupt.
+ *
+ * This helper library can be used independently of the modeset helper library.
+ * Drivers can also overwrite different parts e.g. use their own hotplug
+ * handling code to avoid probing unrelated outputs.
+ */
+
+static bool drm_kms_helper_poll = true;
+module_param_named(poll, drm_kms_helper_poll, bool, 0600);
+
+static void drm_mode_validate_flag(struct drm_connector *connector,
+ int flags)
+{
+ struct drm_display_mode *mode;
+
+ if (flags == (DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_INTERLACE |
+ DRM_MODE_FLAG_3D_MASK))
+ return;
+
+ list_for_each_entry(mode, &connector->modes, head) {
+ if ((mode->flags & DRM_MODE_FLAG_INTERLACE) &&
+ !(flags & DRM_MODE_FLAG_INTERLACE))
+ mode->status = MODE_NO_INTERLACE;
+ if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) &&
+ !(flags & DRM_MODE_FLAG_DBLSCAN))
+ mode->status = MODE_NO_DBLESCAN;
+ if ((mode->flags & DRM_MODE_FLAG_3D_MASK) &&
+ !(flags & DRM_MODE_FLAG_3D_MASK))
+ mode->status = MODE_NO_STEREO;
+ }
+
+ return;
+}
+
+/**
+ * drm_helper_probe_single_connector_modes - get complete set of display modes
+ * @connector: connector to probe
+ * @maxX: max width for modes
+ * @maxY: max height for modes
+ *
+ * Based on the helper callbacks implemented by @connector try to detect all
+ * valid modes. Modes will first be added to the connector's probed_modes list,
+ * then culled (based on validity and the @maxX, @maxY parameters) and put into
+ * the normal modes list.
+ *
+ * Intended to be use as a generic implementation of the ->fill_modes()
+ * @connector vfunc for drivers that use the crtc helpers for output mode
+ * filtering and detection.
+ *
+ * Returns:
+ * The number of modes found on @connector.
+ */
+int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
+ uint32_t maxX, uint32_t maxY)
+{
+ struct drm_device *dev = connector->dev;
+ struct drm_display_mode *mode;
+ struct drm_connector_helper_funcs *connector_funcs =
+ connector->helper_private;
+ int count = 0;
+ int mode_flags = 0;
+ bool verbose_prune = true;
+
+ WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
+
+ DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id,
+ drm_get_connector_name(connector));
+ /* set all modes to the unverified state */
+ list_for_each_entry(mode, &connector->modes, head)
+ mode->status = MODE_UNVERIFIED;
+
+ if (connector->force) {
+ if (connector->force == DRM_FORCE_ON)
+ connector->status = connector_status_connected;
+ else
+ connector->status = connector_status_disconnected;
+ if (connector->funcs->force)
+ connector->funcs->force(connector);
+ } else {
+ connector->status = connector->funcs->detect(connector, true);
+ }
+
+ /* Re-enable polling in case the global poll config changed. */
+ if (drm_kms_helper_poll != dev->mode_config.poll_running)
+ drm_kms_helper_poll_enable(dev);
+
+ dev->mode_config.poll_running = drm_kms_helper_poll;
+
+ if (connector->status == connector_status_disconnected) {
+ DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n",
+ connector->base.id, drm_get_connector_name(connector));
+ drm_mode_connector_update_edid_property(connector, NULL);
+ verbose_prune = false;
+ goto prune;
+ }
+
+#ifdef CONFIG_DRM_LOAD_EDID_FIRMWARE
+ count = drm_load_edid_firmware(connector);
+ if (count == 0)
+#endif
+ count = (*connector_funcs->get_modes)(connector);
+
+ if (count == 0 && connector->status == connector_status_connected)
+ count = drm_add_modes_noedid(connector, 1024, 768);
+ if (count == 0)
+ goto prune;
+
+ drm_mode_connector_list_update(connector);
+
+ if (maxX && maxY)
+ drm_mode_validate_size(dev, &connector->modes, maxX, maxY);
+
+ if (connector->interlace_allowed)
+ mode_flags |= DRM_MODE_FLAG_INTERLACE;
+ if (connector->doublescan_allowed)
+ mode_flags |= DRM_MODE_FLAG_DBLSCAN;
+ if (connector->stereo_allowed)
+ mode_flags |= DRM_MODE_FLAG_3D_MASK;
+ drm_mode_validate_flag(connector, mode_flags);
+
+ list_for_each_entry(mode, &connector->modes, head) {
+ if (mode->status == MODE_OK)
+ mode->status = connector_funcs->mode_valid(connector,
+ mode);
+ }
+
+prune:
+ drm_mode_prune_invalid(dev, &connector->modes, verbose_prune);
+
+ if (list_empty(&connector->modes))
+ return 0;
+
+ list_for_each_entry(mode, &connector->modes, head)
+ mode->vrefresh = drm_mode_vrefresh(mode);
+
+ drm_mode_sort(&connector->modes);
+
+ DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed modes :\n", connector->base.id,
+ drm_get_connector_name(connector));
+ list_for_each_entry(mode, &connector->modes, head) {
+ drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
+ drm_mode_debug_printmodeline(mode);
+ }
+
+ return count;
+}
+EXPORT_SYMBOL(drm_helper_probe_single_connector_modes);
+
+/**
+ * drm_kms_helper_hotplug_event - fire off KMS hotplug events
+ * @dev: drm_device whose connector state changed
+ *
+ * This function fires off the uevent for userspace and also calls the
+ * output_poll_changed function, which is most commonly used to inform the fbdev
+ * emulation code and allow it to update the fbcon output configuration.
+ *
+ * Drivers should call this from their hotplug handling code when a change is
+ * detected. Note that this function does not do any output detection of its
+ * own, like drm_helper_hpd_irq_event() does - this is assumed to be done by the
+ * driver already.
+ *
+ * This function must be called from process context with no mode
+ * setting locks held.
+ */
+void drm_kms_helper_hotplug_event(struct drm_device *dev)
+{
+ /* send a uevent + call fbdev */
+ drm_sysfs_hotplug_event(dev);
+ if (dev->mode_config.funcs->output_poll_changed)
+ dev->mode_config.funcs->output_poll_changed(dev);
+}
+EXPORT_SYMBOL(drm_kms_helper_hotplug_event);
+
+#define DRM_OUTPUT_POLL_PERIOD (10*HZ)
+static void output_poll_execute(struct work_struct *work)
+{
+ struct delayed_work *delayed_work = to_delayed_work(work);
+ struct drm_device *dev = container_of(delayed_work, struct drm_device, mode_config.output_poll_work);
+ struct drm_connector *connector;
+ enum drm_connector_status old_status;
+ bool repoll = false, changed = false;
+
+ if (!drm_kms_helper_poll)
+ return;
+
+ mutex_lock(&dev->mode_config.mutex);
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+
+ /* Ignore forced connectors. */
+ if (connector->force)
+ continue;
+
+ /* Ignore HPD capable connectors and connectors where we don't
+ * want any hotplug detection at all for polling. */
+ if (!connector->polled || connector->polled == DRM_CONNECTOR_POLL_HPD)
+ continue;
+
+ repoll = true;
+
+ old_status = connector->status;
+ /* if we are connected and don't want to poll for disconnect
+ skip it */
+ if (old_status == connector_status_connected &&
+ !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT))
+ continue;
+
+ connector->status = connector->funcs->detect(connector, false);
+ if (old_status != connector->status) {
+ const char *old, *new;
+
+ old = drm_get_connector_status_name(old_status);
+ new = drm_get_connector_status_name(connector->status);
+
+ DRM_DEBUG_KMS("[CONNECTOR:%d:%s] "
+ "status updated from %s to %s\n",
+ connector->base.id,
+ drm_get_connector_name(connector),
+ old, new);
+
+ changed = true;
+ }
+ }
+
+ mutex_unlock(&dev->mode_config.mutex);
+
+ if (changed)
+ drm_kms_helper_hotplug_event(dev);
+
+ if (repoll)
+ schedule_delayed_work(delayed_work, DRM_OUTPUT_POLL_PERIOD);
+}
+
+/**
+ * drm_kms_helper_poll_disable - disable output polling
+ * @dev: drm_device
+ *
+ * This function disables the output polling work.
+ *
+ * Drivers can call this helper from their device suspend implementation. It is
+ * not an error to call this even when output polling isn't enabled or arlready
+ * disabled.
+ */
+void drm_kms_helper_poll_disable(struct drm_device *dev)
+{
+ if (!dev->mode_config.poll_enabled)
+ return;
+ cancel_delayed_work_sync(&dev->mode_config.output_poll_work);
+}
+EXPORT_SYMBOL(drm_kms_helper_poll_disable);
+
+/**
+ * drm_kms_helper_poll_enable - re-enable output polling.
+ * @dev: drm_device
+ *
+ * This function re-enables the output polling work.
+ *
+ * Drivers can call this helper from their device resume implementation. It is
+ * an error to call this when the output polling support has not yet been set
+ * up.
+ */
+void drm_kms_helper_poll_enable(struct drm_device *dev)
+{
+ bool poll = false;
+ struct drm_connector *connector;
+
+ if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll)
+ return;
+
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+ if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT |
+ DRM_CONNECTOR_POLL_DISCONNECT))
+ poll = true;
+ }
+
+ if (poll)
+ schedule_delayed_work(&dev->mode_config.output_poll_work, DRM_OUTPUT_POLL_PERIOD);
+}
+EXPORT_SYMBOL(drm_kms_helper_poll_enable);
+
+/**
+ * drm_kms_helper_poll_init - initialize and enable output polling
+ * @dev: drm_device
+ *
+ * This function intializes and then also enables output polling support for
+ * @dev. Drivers which do not have reliable hotplug support in hardware can use
+ * this helper infrastructure to regularly poll such connectors for changes in
+ * their connection state.
+ *
+ * Drivers can control which connectors are polled by setting the
+ * DRM_CONNECTOR_POLL_CONNECT and DRM_CONNECTOR_POLL_DISCONNECT flags. On
+ * connectors where probing live outputs can result in visual distortion drivers
+ * should not set the DRM_CONNECTOR_POLL_DISCONNECT flag to avoid this.
+ * Connectors which have no flag or only DRM_CONNECTOR_POLL_HPD set are
+ * completely ignored by the polling logic.
+ *
+ * Note that a connector can be both polled and probed from the hotplug handler,
+ * in case the hotplug interrupt is known to be unreliable.
+ */
+void drm_kms_helper_poll_init(struct drm_device *dev)
+{
+ INIT_DELAYED_WORK(&dev->mode_config.output_poll_work, output_poll_execute);
+ dev->mode_config.poll_enabled = true;
+
+ drm_kms_helper_poll_enable(dev);
+}
+EXPORT_SYMBOL(drm_kms_helper_poll_init);
+
+/**
+ * drm_kms_helper_poll_fini - disable output polling and clean it up
+ * @dev: drm_device
+ */
+void drm_kms_helper_poll_fini(struct drm_device *dev)
+{
+ drm_kms_helper_poll_disable(dev);
+}
+EXPORT_SYMBOL(drm_kms_helper_poll_fini);
+
+/**
+ * drm_helper_hpd_irq_event - hotplug processing
+ * @dev: drm_device
+ *
+ * Drivers can use this helper function to run a detect cycle on all connectors
+ * which have the DRM_CONNECTOR_POLL_HPD flag set in their &polled member. All
+ * other connectors are ignored, which is useful to avoid reprobing fixed
+ * panels.
+ *
+ * This helper function is useful for drivers which can't or don't track hotplug
+ * interrupts for each connector.
+ *
+ * Drivers which support hotplug interrupts for each connector individually and
+ * which have a more fine-grained detect logic should bypass this code and
+ * directly call drm_kms_helper_hotplug_event() in case the connector state
+ * changed.
+ *
+ * This function must be called from process context with no mode
+ * setting locks held.
+ *
+ * Note that a connector can be both polled and probed from the hotplug handler,
+ * in case the hotplug interrupt is known to be unreliable.
+ */
+bool drm_helper_hpd_irq_event(struct drm_device *dev)
+{
+ struct drm_connector *connector;
+ enum drm_connector_status old_status;
+ bool changed = false;
+
+ if (!dev->mode_config.poll_enabled)
+ return false;
+
+ mutex_lock(&dev->mode_config.mutex);
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+
+ /* Only handle HPD capable connectors. */
+ if (!(connector->polled & DRM_CONNECTOR_POLL_HPD))
+ continue;
+
+ old_status = connector->status;
+
+ connector->status = connector->funcs->detect(connector, false);
+ DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n",
+ connector->base.id,
+ drm_get_connector_name(connector),
+ drm_get_connector_status_name(old_status),
+ drm_get_connector_status_name(connector->status));
+ if (old_status != connector->status)
+ changed = true;
+ }
+
+ mutex_unlock(&dev->mode_config.mutex);
+
+ if (changed)
+ drm_kms_helper_hotplug_event(dev);
+
+ return changed;
+}
+EXPORT_SYMBOL(drm_helper_hpd_irq_event);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index e930d4fe29c7..1ef5ab9c9d51 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -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;
}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
index c786cd4f457b..2a3ad24276f8 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
@@ -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;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index eb73e3bf2a0c..4ac438187568 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -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");
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index 7afead9c3f30..852f2dadaebd 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -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);
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 96177eec0a0e..eedb023af27d 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -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);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 0905cd915589..388c028e223c 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -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;
@@ -1308,6 +1293,7 @@ struct intel_vbt_data {
struct {
u16 pwm_freq_hz;
+ bool present;
bool active_low_pwm;
} backlight;
@@ -1768,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)
@@ -1953,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)
/*
@@ -2200,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);
@@ -2330,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);
@@ -2431,20 +2417,18 @@ int i915_gem_context_open(struct drm_device *dev, struct drm_file *file);
int i915_gem_context_enable(struct drm_i915_private *dev_priv);
void i915_gem_context_close(struct drm_device *dev, struct drm_file *file);
int i915_switch_context(struct intel_ring_buffer *ring,
- struct drm_file *file, struct i915_hw_context *to);
+ struct i915_hw_context *to);
struct i915_hw_context *
i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id);
void i915_gem_context_free(struct kref *ctx_ref);
static inline void i915_gem_context_reference(struct i915_hw_context *ctx)
{
- if (ctx->obj && HAS_HW_CONTEXTS(ctx->obj->base.dev))
- kref_get(&ctx->ref);
+ kref_get(&ctx->ref);
}
static inline void i915_gem_context_unreference(struct i915_hw_context *ctx)
{
- if (ctx->obj && HAS_HW_CONTEXTS(ctx->obj->base.dev))
- kref_put(&ctx->ref, i915_gem_context_free);
+ kref_put(&ctx->ref, i915_gem_context_free);
}
static inline bool i915_gem_context_is_default(const struct i915_hw_context *c)
@@ -2463,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);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 6370a761d137..3326770c9ed2 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -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;
}
@@ -2790,7 +2908,7 @@ int i915_gpu_idle(struct drm_device *dev)
/* Flush everything onto the inactive list. */
for_each_ring(ring, dev_priv, i) {
- ret = i915_switch_context(ring, NULL, ring->default_context);
+ ret = i915_switch_context(ring, ring->default_context);
if (ret)
return ret;
@@ -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;
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index 6043062ffce7..d72db15afa02 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -96,9 +96,6 @@
#define GEN6_CONTEXT_ALIGN (64<<10)
#define GEN7_CONTEXT_ALIGN 4096
-static int do_switch(struct intel_ring_buffer *ring,
- struct i915_hw_context *to);
-
static void do_ppgtt_cleanup(struct i915_hw_ppgtt *ppgtt)
{
struct drm_device *dev = ppgtt->base.dev;
@@ -185,13 +182,15 @@ void i915_gem_context_free(struct kref *ctx_ref)
typeof(*ctx), ref);
struct i915_hw_ppgtt *ppgtt = NULL;
- /* We refcount even the aliasing PPGTT to keep the code symmetric */
- if (USES_PPGTT(ctx->obj->base.dev))
- ppgtt = ctx_to_ppgtt(ctx);
+ if (ctx->obj) {
+ /* We refcount even the aliasing PPGTT to keep the code symmetric */
+ if (USES_PPGTT(ctx->obj->base.dev))
+ ppgtt = ctx_to_ppgtt(ctx);
- /* XXX: Free up the object before tearing down the address space, in
- * case we're bound in the PPGTT */
- drm_gem_object_unreference(&ctx->obj->base);
+ /* XXX: Free up the object before tearing down the address space, in
+ * case we're bound in the PPGTT */
+ drm_gem_object_unreference(&ctx->obj->base);
+ }
if (ppgtt)
kref_put(&ppgtt->ref, ppgtt_release);
@@ -232,32 +231,32 @@ __create_hw_context(struct drm_device *dev,
return ERR_PTR(-ENOMEM);
kref_init(&ctx->ref);
- ctx->obj = i915_gem_alloc_object(dev, dev_priv->hw_context_size);
- INIT_LIST_HEAD(&ctx->link);
- if (ctx->obj == NULL) {
- kfree(ctx);
- DRM_DEBUG_DRIVER("Context object allocated failed\n");
- return ERR_PTR(-ENOMEM);
- }
+ list_add_tail(&ctx->link, &dev_priv->context_list);
- if (INTEL_INFO(dev)->gen >= 7) {
- ret = i915_gem_object_set_cache_level(ctx->obj,
- I915_CACHE_L3_LLC);
- /* Failure shouldn't ever happen this early */
- if (WARN_ON(ret))
+ if (dev_priv->hw_context_size) {
+ ctx->obj = i915_gem_alloc_object(dev, dev_priv->hw_context_size);
+ if (ctx->obj == NULL) {
+ ret = -ENOMEM;
goto err_out;
- }
+ }
- list_add_tail(&ctx->link, &dev_priv->context_list);
+ if (INTEL_INFO(dev)->gen >= 7) {
+ ret = i915_gem_object_set_cache_level(ctx->obj,
+ I915_CACHE_L3_LLC);
+ /* Failure shouldn't ever happen this early */
+ if (WARN_ON(ret))
+ goto err_out;
+ }
+ }
/* Default context will never have a file_priv */
- if (file_priv == NULL)
- return ctx;
-
- ret = idr_alloc(&file_priv->context_idr, ctx, DEFAULT_CONTEXT_ID, 0,
- GFP_KERNEL);
- if (ret < 0)
- goto err_out;
+ if (file_priv != NULL) {
+ ret = idr_alloc(&file_priv->context_idr, ctx,
+ DEFAULT_CONTEXT_ID, 0, GFP_KERNEL);
+ if (ret < 0)
+ goto err_out;
+ } else
+ ret = DEFAULT_CONTEXT_ID;
ctx->file_priv = file_priv;
ctx->id = ret;
@@ -294,7 +293,7 @@ i915_gem_create_context(struct drm_device *dev,
if (IS_ERR(ctx))
return ctx;
- if (is_global_default_ctx) {
+ if (is_global_default_ctx && ctx->obj) {
/* We may need to do things with the shrinker which
* require us to immediately switch back to the default
* context. This can cause a problem as pinning the
@@ -342,7 +341,7 @@ i915_gem_create_context(struct drm_device *dev,
return ctx;
err_unpin:
- if (is_global_default_ctx)
+ if (is_global_default_ctx && ctx->obj)
i915_gem_object_ggtt_unpin(ctx->obj);
err_destroy:
i915_gem_context_unreference(ctx);
@@ -352,32 +351,22 @@ err_destroy:
void i915_gem_context_reset(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_ring_buffer *ring;
int i;
- if (!HAS_HW_CONTEXTS(dev))
- return;
-
/* Prevent the hardware from restoring the last context (which hung) on
* the next switch */
for (i = 0; i < I915_NUM_RINGS; i++) {
- struct i915_hw_context *dctx;
- if (!(INTEL_INFO(dev)->ring_mask & (1<<i)))
- continue;
+ struct intel_ring_buffer *ring = &dev_priv->ring[i];
+ struct i915_hw_context *dctx = ring->default_context;
/* Do a fake switch to the default context */
- ring = &dev_priv->ring[i];
- dctx = ring->default_context;
- if (WARN_ON(!dctx))
+ if (ring->last_context == dctx)
continue;
if (!ring->last_context)
continue;
- if (ring->last_context == dctx)
- continue;
-
- if (i == RCS) {
+ if (dctx->obj && i == RCS) {
WARN_ON(i915_gem_obj_ggtt_pin(dctx->obj,
get_context_alignment(dev), 0));
/* Fake a finish/inactive */
@@ -394,44 +383,35 @@ void i915_gem_context_reset(struct drm_device *dev)
int i915_gem_context_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_ring_buffer *ring;
+ struct i915_hw_context *ctx;
int i;
- if (!HAS_HW_CONTEXTS(dev))
- return 0;
-
/* Init should only be called once per module load. Eventually the
* restriction on the context_disabled check can be loosened. */
if (WARN_ON(dev_priv->ring[RCS].default_context))
return 0;
- dev_priv->hw_context_size = round_up(get_context_size(dev), 4096);
-
- if (dev_priv->hw_context_size > (1<<20)) {
- DRM_DEBUG_DRIVER("Disabling HW Contexts; invalid size\n");
- return -E2BIG;
+ if (HAS_HW_CONTEXTS(dev)) {
+ dev_priv->hw_context_size = round_up(get_context_size(dev), 4096);
+ if (dev_priv->hw_context_size > (1<<20)) {
+ DRM_DEBUG_DRIVER("Disabling HW Contexts; invalid size %d\n",
+ dev_priv->hw_context_size);
+ dev_priv->hw_context_size = 0;
+ }
}
- dev_priv->ring[RCS].default_context =
- i915_gem_create_context(dev, NULL, USES_PPGTT(dev));
-
- if (IS_ERR_OR_NULL(dev_priv->ring[RCS].default_context)) {
- DRM_DEBUG_DRIVER("Disabling HW Contexts; create failed %ld\n",
- PTR_ERR(dev_priv->ring[RCS].default_context));
- return PTR_ERR(dev_priv->ring[RCS].default_context);
+ ctx = i915_gem_create_context(dev, NULL, USES_PPGTT(dev));
+ if (IS_ERR(ctx)) {
+ DRM_ERROR("Failed to create default global context (error %ld)\n",
+ PTR_ERR(ctx));
+ return PTR_ERR(ctx);
}
- for (i = RCS + 1; i < I915_NUM_RINGS; i++) {
- if (!(INTEL_INFO(dev)->ring_mask & (1<<i)))
- continue;
-
- ring = &dev_priv->ring[i];
+ /* NB: RCS will hold a ref for all rings */
+ for (i = 0; i < I915_NUM_RINGS; i++)
+ dev_priv->ring[i].default_context = ctx;
- /* NB: RCS will hold a ref for all rings */
- ring->default_context = dev_priv->ring[RCS].default_context;
- }
-
- DRM_DEBUG_DRIVER("HW context support initialized\n");
+ DRM_DEBUG_DRIVER("%s context support initialized\n", dev_priv->hw_context_size ? "HW" : "fake");
return 0;
}
@@ -441,33 +421,30 @@ void i915_gem_context_fini(struct drm_device *dev)
struct i915_hw_context *dctx = dev_priv->ring[RCS].default_context;
int i;
- if (!HAS_HW_CONTEXTS(dev))
- return;
-
- /* The only known way to stop the gpu from accessing the hw context is
- * to reset it. Do this as the very last operation to avoid confusing
- * other code, leading to spurious errors. */
- intel_gpu_reset(dev);
-
- /* When default context is created and switched to, base object refcount
- * will be 2 (+1 from object creation and +1 from do_switch()).
- * i915_gem_context_fini() will be called after gpu_idle() has switched
- * to default context. So we need to unreference the base object once
- * to offset the do_switch part, so that i915_gem_context_unreference()
- * can then free the base object correctly. */
- WARN_ON(!dev_priv->ring[RCS].last_context);
- if (dev_priv->ring[RCS].last_context == dctx) {
- /* Fake switch to NULL context */
- WARN_ON(dctx->obj->active);
- i915_gem_object_ggtt_unpin(dctx->obj);
- i915_gem_context_unreference(dctx);
- dev_priv->ring[RCS].last_context = NULL;
+ if (dctx->obj) {
+ /* The only known way to stop the gpu from accessing the hw context is
+ * to reset it. Do this as the very last operation to avoid confusing
+ * other code, leading to spurious errors. */
+ intel_gpu_reset(dev);
+
+ /* When default context is created and switched to, base object refcount
+ * will be 2 (+1 from object creation and +1 from do_switch()).
+ * i915_gem_context_fini() will be called after gpu_idle() has switched
+ * to default context. So we need to unreference the base object once
+ * to offset the do_switch part, so that i915_gem_context_unreference()
+ * can then free the base object correctly. */
+ WARN_ON(!dev_priv->ring[RCS].last_context);
+ if (dev_priv->ring[RCS].last_context == dctx) {
+ /* Fake switch to NULL context */
+ WARN_ON(dctx->obj->active);
+ i915_gem_object_ggtt_unpin(dctx->obj);
+ i915_gem_context_unreference(dctx);
+ dev_priv->ring[RCS].last_context = NULL;
+ }
}
for (i = 0; i < I915_NUM_RINGS; i++) {
struct intel_ring_buffer *ring = &dev_priv->ring[i];
- if (!(INTEL_INFO(dev)->ring_mask & (1<<i)))
- continue;
if (ring->last_context)
i915_gem_context_unreference(ring->last_context);
@@ -478,7 +455,6 @@ void i915_gem_context_fini(struct drm_device *dev)
i915_gem_object_ggtt_unpin(dctx->obj);
i915_gem_context_unreference(dctx);
- dev_priv->mm.aliasing_ppgtt = NULL;
}
int i915_gem_context_enable(struct drm_i915_private *dev_priv)
@@ -486,9 +462,6 @@ int i915_gem_context_enable(struct drm_i915_private *dev_priv)
struct intel_ring_buffer *ring;
int ret, i;
- if (!HAS_HW_CONTEXTS(dev_priv->dev))
- return 0;
-
/* This is the only place the aliasing PPGTT gets enabled, which means
* it has to happen before we bail on reset */
if (dev_priv->mm.aliasing_ppgtt) {
@@ -503,7 +476,7 @@ int i915_gem_context_enable(struct drm_i915_private *dev_priv)
BUG_ON(!dev_priv->ring[RCS].default_context);
for_each_ring(ring, dev_priv, i) {
- ret = do_switch(ring, ring->default_context);
+ ret = i915_switch_context(ring, ring->default_context);
if (ret)
return ret;
}
@@ -526,19 +499,6 @@ static int context_idr_cleanup(int id, void *p, void *data)
int i915_gem_context_open(struct drm_device *dev, struct drm_file *file)
{
struct drm_i915_file_private *file_priv = file->driver_priv;
- struct drm_i915_private *dev_priv = dev->dev_private;
-
- if (!HAS_HW_CONTEXTS(dev)) {
- /* Cheat for hang stats */
- file_priv->private_default_ctx =
- kzalloc(sizeof(struct i915_hw_context), GFP_KERNEL);
-
- if (file_priv->private_default_ctx == NULL)
- return -ENOMEM;
-
- file_priv->private_default_ctx->vm = &dev_priv->gtt.base;
- return 0;
- }
idr_init(&file_priv->context_idr);
@@ -559,14 +519,10 @@ void i915_gem_context_close(struct drm_device *dev, struct drm_file *file)
{
struct drm_i915_file_private *file_priv = file->driver_priv;
- if (!HAS_HW_CONTEXTS(dev)) {
- kfree(file_priv->private_default_ctx);
- return;
- }
-
idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL);
- i915_gem_context_unreference(file_priv->private_default_ctx);
idr_destroy(&file_priv->context_idr);
+
+ i915_gem_context_unreference(file_priv->private_default_ctx);
}
struct i915_hw_context *
@@ -574,9 +530,6 @@ i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id)
{
struct i915_hw_context *ctx;
- if (!HAS_HW_CONTEXTS(file_priv->dev_priv->dev))
- return file_priv->private_default_ctx;
-
ctx = (struct i915_hw_context *)idr_find(&file_priv->context_idr, id);
if (!ctx)
return ERR_PTR(-ENOENT);
@@ -758,7 +711,6 @@ unpin_out:
/**
* i915_switch_context() - perform a GPU context switch.
* @ring: ring for which we'll execute the context switch
- * @file_priv: file_priv associated with the context, may be NULL
* @to: the context to switch to
*
* The context life cycle is simple. The context refcount is incremented and
@@ -767,24 +719,30 @@ unpin_out:
* object while letting the normal object tracking destroy the backing BO.
*/
int i915_switch_context(struct intel_ring_buffer *ring,
- struct drm_file *file,
struct i915_hw_context *to)
{
struct drm_i915_private *dev_priv = ring->dev->dev_private;
WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
- BUG_ON(file && to == NULL);
-
- /* We have the fake context */
- if (!HAS_HW_CONTEXTS(ring->dev)) {
- ring->last_context = to;
+ if (to->obj == NULL) { /* We have the fake context */
+ if (to != ring->last_context) {
+ i915_gem_context_reference(to);
+ if (ring->last_context)
+ i915_gem_context_unreference(ring->last_context);
+ ring->last_context = to;
+ }
return 0;
}
return do_switch(ring, to);
}
+static bool hw_context_enabled(struct drm_device *dev)
+{
+ return to_i915(dev)->hw_context_size;
+}
+
int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
struct drm_file *file)
{
@@ -793,7 +751,7 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
struct i915_hw_context *ctx;
int ret;
- if (!HAS_HW_CONTEXTS(dev))
+ if (!hw_context_enabled(dev))
return -ENODEV;
ret = i915_mutex_lock_interruptible(dev);
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
index 75fca63dc8c1..bbf4b12d842e 100644
--- a/drivers/gpu/drm/i915/i915_gem_evict.c
+++ b/drivers/gpu/drm/i915/i915_gem_evict.c
@@ -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);
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 7447160155a3..20fef6c50267 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -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;
@@ -1221,7 +1259,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
if (ret)
goto err;
- ret = i915_switch_context(ring, file, ctx);
+ ret = i915_switch_context(ring, ctx);
if (ret)
goto err;
@@ -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;
+ }
}
}
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index ab5e93c30aa2..5deb22864c52 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -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;
}
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 7753249b3a95..f98ba4e6e70b 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -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)
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 9f5b18d9d885..c77af69c2d8f 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -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
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index 4867f4cc0938..aff4a113cda3 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -287,6 +287,9 @@ parse_lfp_backlight(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
const struct bdb_lfp_backlight_data *backlight_data;
const struct bdb_lfp_backlight_data_entry *entry;
+ /* Err to enabling backlight if no backlight block. */
+ dev_priv->vbt.backlight.present = true;
+
backlight_data = find_section(bdb, BDB_LVDS_BACKLIGHT);
if (!backlight_data)
return;
@@ -299,6 +302,13 @@ parse_lfp_backlight(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
entry = &backlight_data->data[panel_type];
+ dev_priv->vbt.backlight.present = entry->type == BDB_BACKLIGHT_TYPE_PWM;
+ if (!dev_priv->vbt.backlight.present) {
+ DRM_DEBUG_KMS("PWM backlight not present in VBT (type %u)\n",
+ entry->type);
+ return;
+ }
+
dev_priv->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz;
dev_priv->vbt.backlight.active_low_pwm = entry->active_low_pwm;
DRM_DEBUG_KMS("VBT backlight PWM modulation frequency %u Hz, "
@@ -550,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;
}
}
diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h
index 83b7629e4367..f27f7b282465 100644
--- a/drivers/gpu/drm/i915/intel_bios.h
+++ b/drivers/gpu/drm/i915/intel_bios.h
@@ -374,6 +374,9 @@ struct bdb_lvds_lfp_data {
struct bdb_lvds_lfp_data_entry data[16];
} __packed;
+#define BDB_BACKLIGHT_TYPE_NONE 0
+#define BDB_BACKLIGHT_TYPE_PWM 2
+
struct bdb_lfp_backlight_data_entry {
u8 type:2;
u8 active_low_pwm:1;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index dae976f51d83..5b60e25baa32 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -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);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index a0dad1a2f819..2a00cb828d20 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -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);
@@ -575,7 +592,8 @@ out:
return ret;
}
-#define HEADER_SIZE 4
+#define BARE_ADDRESS_SIZE 3
+#define HEADER_SIZE (BARE_ADDRESS_SIZE + 1)
static ssize_t
intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
{
@@ -592,7 +610,7 @@ intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
switch (msg->request & ~DP_AUX_I2C_MOT) {
case DP_AUX_NATIVE_WRITE:
case DP_AUX_I2C_WRITE:
- txsize = HEADER_SIZE + msg->size;
+ txsize = msg->size ? HEADER_SIZE + msg->size : BARE_ADDRESS_SIZE;
rxsize = 1;
if (WARN_ON(txsize > 20))
@@ -611,7 +629,7 @@ intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
case DP_AUX_NATIVE_READ:
case DP_AUX_I2C_READ:
- txsize = HEADER_SIZE;
+ txsize = msg->size ? HEADER_SIZE : BARE_ADDRESS_SIZE;
rxsize = msg->size + 1;
if (WARN_ON(rxsize > 20))
@@ -749,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 };
@@ -783,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);
@@ -3618,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;
@@ -3628,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);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 0542de982260..328b1a70264b 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -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
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index b4d44e62f0c7..f73ba5e6b7a8 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -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]) {
/*
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index b0413e190625..157267aa3561 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -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) {
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index d8adc9104dca..129db0c7d835 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -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);
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index cb058408c70e..cb8cfb7e0974 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -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)
@@ -1065,6 +1065,11 @@ int intel_panel_setup_backlight(struct drm_connector *connector)
unsigned long flags;
int ret;
+ if (!dev_priv->vbt.backlight.present) {
+ DRM_DEBUG_KMS("native backlight control not available per VBT\n");
+ return 0;
+ }
+
/* set level and max in panel struct */
spin_lock_irqsave(&dev_priv->backlight_lock, flags);
ret = dev_priv->display.setup_backlight(intel_connector);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 5874716774a7..d93dcf683e8c 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -1545,6 +1545,16 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
DRM_DEBUG_KMS("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm);
+ if (IS_I915GM(dev) && enabled) {
+ struct intel_framebuffer *fb;
+
+ fb = to_intel_framebuffer(enabled->primary->fb);
+
+ /* self-refresh seems busted with untiled */
+ if (fb->obj->tiling_mode == I915_TILING_NONE)
+ enabled = NULL;
+ }
+
/*
* Overlay gets an aggressive default since video jitter is bad.
*/
@@ -2085,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;
@@ -2102,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,
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 6bc68bdcf433..79fb4cc2137c 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -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
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 270a6a973438..2b91c4b4d34b 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -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,
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index d27155adf5db..46be00d66df3 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -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;
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index f729dc71d5be..d0c75779d3f6 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -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);
}
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
index 3e6c0f3ed592..ef9957dbac94 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
@@ -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;
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c
index c740ccd1cc67..8edd531cb621 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c
@@ -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;
}
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
index 272e707c9487..0bb4faa17523 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
@@ -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:
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
index 66a4d31aec80..715520c54cde 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
@@ -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)
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c
index 353d494a497f..f2b985bc2adf 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c
@@ -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)
diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c
index 6c6d7d4c9b4e..a752ab83b810 100644
--- a/drivers/gpu/drm/msm/msm_fbdev.c
+++ b/drivers/gpu/drm/msm/msm_fbdev.c
@@ -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,
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index 3da8264d3039..bb8026daebc9 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -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;
}
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
index 7762665ad8fd..876de9ac3793 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
@@ -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)
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c
index 1dc37b1ddbfa..b0d0fb2f4d08 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c
@@ -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);
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c
index e9df94f96d78..222e8ebb669d 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c
@@ -109,7 +109,7 @@ nouveau_bios_shadow_pramin(struct nouveau_bios *bios)
return;
}
- addr = (u64)(addr >> 8) << 8;
+ addr = (addr & 0xffffff00) << 8;
if (!addr) {
addr = (u64)nv_rd32(bios, 0x001700) << 16;
addr += 0xf0000;
@@ -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 */
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c
index 43fec17ea540..bbf117be572f 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c
@@ -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;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c
index 83face3f608f..279206997e5c 100644
--- a/drivers/gpu/drm/nouveau/nouveau_acpi.c
+++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c
@@ -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;
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 3ff030dc1ee3..da764a4ed958 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -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;
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index 355157e4f78d..e3c47a8005ff 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -33,6 +33,7 @@ struct omap_crtc {
int pipe;
enum omap_channel channel;
struct omap_overlay_manager_info info;
+ struct drm_encoder *current_encoder;
/*
* Temporary: eventually this will go away, but it is needed
@@ -120,13 +121,25 @@ static void omap_crtc_start_update(struct omap_overlay_manager *mgr)
{
}
+static void set_enabled(struct drm_crtc *crtc, bool enable);
+
static int omap_crtc_enable(struct omap_overlay_manager *mgr)
{
+ struct omap_crtc *omap_crtc = omap_crtcs[mgr->id];
+
+ dispc_mgr_setup(omap_crtc->channel, &omap_crtc->info);
+ dispc_mgr_set_timings(omap_crtc->channel,
+ &omap_crtc->timings);
+ set_enabled(&omap_crtc->base, true);
+
return 0;
}
static void omap_crtc_disable(struct omap_overlay_manager *mgr)
{
+ struct omap_crtc *omap_crtc = omap_crtcs[mgr->id];
+
+ set_enabled(&omap_crtc->base, false);
}
static void omap_crtc_set_timings(struct omap_overlay_manager *mgr,
@@ -184,7 +197,6 @@ static void omap_crtc_destroy(struct drm_crtc *crtc)
WARN_ON(omap_crtc->apply_irq.registered);
omap_irq_unregister(crtc->dev, &omap_crtc->error_irq);
- omap_crtc->plane->funcs->destroy(omap_crtc->plane);
drm_crtc_cleanup(crtc);
kfree(omap_crtc);
@@ -338,17 +350,23 @@ static int omap_crtc_page_flip_locked(struct drm_crtc *crtc,
struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
struct drm_plane *primary = crtc->primary;
struct drm_gem_object *bo;
+ unsigned long flags;
DBG("%d -> %d (event=%p)", primary->fb ? primary->fb->base.id : -1,
fb->base.id, event);
+ spin_lock_irqsave(&dev->event_lock, flags);
+
if (omap_crtc->old_fb) {
+ spin_unlock_irqrestore(&dev->event_lock, flags);
dev_err(dev->dev, "already a pending flip\n");
return -EINVAL;
}
omap_crtc->event = event;
- primary->fb = fb;
+ omap_crtc->old_fb = primary->fb = fb;
+
+ spin_unlock_irqrestore(&dev->event_lock, flags);
/*
* Hold a reference temporarily until the crtc is updated
@@ -528,38 +546,46 @@ static void set_enabled(struct drm_crtc *crtc, bool enable)
struct drm_device *dev = crtc->dev;
struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
enum omap_channel channel = omap_crtc->channel;
- struct omap_irq_wait *wait = NULL;
+ struct omap_irq_wait *wait;
+ u32 framedone_irq, vsync_irq;
+ int ret;
if (dispc_mgr_is_enabled(channel) == enable)
return;
- /* ignore sync-lost irqs during enable/disable */
+ /*
+ * Digit output produces some sync lost interrupts during the first
+ * frame when enabling, so we need to ignore those.
+ */
omap_irq_unregister(crtc->dev, &omap_crtc->error_irq);
- if (dispc_mgr_get_framedone_irq(channel)) {
- if (!enable) {
- wait = omap_irq_wait_init(dev,
- dispc_mgr_get_framedone_irq(channel), 1);
- }
+ framedone_irq = dispc_mgr_get_framedone_irq(channel);
+ vsync_irq = dispc_mgr_get_vsync_irq(channel);
+
+ if (enable) {
+ wait = omap_irq_wait_init(dev, vsync_irq, 1);
} else {
/*
- * When we disable digit output, we need to wait until fields
- * are done. Otherwise the DSS is still working, and turning
- * off the clocks prevents DSS from going to OFF mode. And when
- * enabling, we need to wait for the extra sync losts
+ * When we disable the digit output, we need to wait for
+ * FRAMEDONE to know that DISPC has finished with the output.
+ *
+ * OMAP2/3 does not have FRAMEDONE irq for digit output, and in
+ * that case we need to use vsync interrupt, and wait for both
+ * even and odd frames.
*/
- wait = omap_irq_wait_init(dev,
- dispc_mgr_get_vsync_irq(channel), 2);
+
+ if (framedone_irq)
+ wait = omap_irq_wait_init(dev, framedone_irq, 1);
+ else
+ wait = omap_irq_wait_init(dev, vsync_irq, 2);
}
dispc_mgr_enable(channel, enable);
- if (wait) {
- int ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100));
- if (ret) {
- dev_err(dev->dev, "%s: timeout waiting for %s\n",
- omap_crtc->name, enable ? "enable" : "disable");
- }
+ ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100));
+ if (ret) {
+ dev_err(dev->dev, "%s: timeout waiting for %s\n",
+ omap_crtc->name, enable ? "enable" : "disable");
}
omap_irq_register(crtc->dev, &omap_crtc->error_irq);
@@ -586,8 +612,12 @@ static void omap_crtc_pre_apply(struct omap_drm_apply *apply)
}
}
+ if (omap_crtc->current_encoder && encoder != omap_crtc->current_encoder)
+ omap_encoder_set_enabled(omap_crtc->current_encoder, false);
+
+ omap_crtc->current_encoder = encoder;
+
if (!omap_crtc->enabled) {
- set_enabled(&omap_crtc->base, false);
if (encoder)
omap_encoder_set_enabled(encoder, false);
} else {
@@ -596,13 +626,7 @@ static void omap_crtc_pre_apply(struct omap_drm_apply *apply)
omap_encoder_update(encoder, omap_crtc->mgr,
&omap_crtc->timings);
omap_encoder_set_enabled(encoder, true);
- omap_crtc->full_update = false;
}
-
- dispc_mgr_setup(omap_crtc->channel, &omap_crtc->info);
- dispc_mgr_set_timings(omap_crtc->channel,
- &omap_crtc->timings);
- set_enabled(&omap_crtc->base, true);
}
omap_crtc->full_update = false;
@@ -613,10 +637,30 @@ static void omap_crtc_post_apply(struct omap_drm_apply *apply)
/* nothing needed for post-apply */
}
+void omap_crtc_flush(struct drm_crtc *crtc)
+{
+ struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+ int loops = 0;
+
+ while (!list_empty(&omap_crtc->pending_applies) ||
+ !list_empty(&omap_crtc->queued_applies) ||
+ omap_crtc->event || omap_crtc->old_fb) {
+
+ if (++loops > 10) {
+ dev_err(crtc->dev->dev,
+ "omap_crtc_flush() timeout\n");
+ break;
+ }
+
+ schedule_timeout_uninterruptible(msecs_to_jiffies(20));
+ }
+}
+
static const char *channel_names[] = {
[OMAP_DSS_CHANNEL_LCD] = "lcd",
[OMAP_DSS_CHANNEL_DIGIT] = "tv",
[OMAP_DSS_CHANNEL_LCD2] = "lcd2",
+ [OMAP_DSS_CHANNEL_LCD3] = "lcd3",
};
void omap_crtc_pre_init(void)
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index bf39fcc49e0f..c8270e4b26f3 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -513,12 +513,18 @@ static int dev_load(struct drm_device *dev, unsigned long flags)
static int dev_unload(struct drm_device *dev)
{
struct omap_drm_private *priv = dev->dev_private;
+ int i;
DBG("unload: dev=%p", dev);
drm_kms_helper_poll_fini(dev);
omap_fbdev_free(dev);
+
+ /* flush crtcs so the fbs get released */
+ for (i = 0; i < priv->num_crtcs; i++)
+ omap_crtc_flush(priv->crtcs[i]);
+
omap_modeset_free(dev);
omap_gem_deinit(dev);
@@ -696,10 +702,11 @@ static int pdev_remove(struct platform_device *device)
{
DBG("");
+ drm_put_dev(platform_get_drvdata(device));
+
omap_disconnect_dssdevs();
omap_crtc_pre_uninit();
- drm_put_dev(platform_get_drvdata(device));
return 0;
}
@@ -726,18 +733,33 @@ static struct platform_driver pdev = {
static int __init omap_drm_init(void)
{
+ int r;
+
DBG("init");
- if (platform_driver_register(&omap_dmm_driver)) {
- /* we can continue on without DMM.. so not fatal */
- dev_err(NULL, "DMM registration failed\n");
+
+ r = platform_driver_register(&omap_dmm_driver);
+ if (r) {
+ pr_err("DMM driver registration failed\n");
+ return r;
+ }
+
+ r = platform_driver_register(&pdev);
+ if (r) {
+ pr_err("omapdrm driver registration failed\n");
+ platform_driver_unregister(&omap_dmm_driver);
+ return r;
}
- return platform_driver_register(&pdev);
+
+ return 0;
}
static void __exit omap_drm_fini(void)
{
DBG("fini");
+
platform_driver_unregister(&pdev);
+
+ platform_driver_unregister(&omap_dmm_driver);
}
/* need late_initcall() so we load after dss_driver's are loaded */
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index 428b2981fd68..284b80fc3c54 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -163,6 +163,7 @@ void omap_crtc_pre_init(void);
void omap_crtc_pre_uninit(void);
struct drm_crtc *omap_crtc_init(struct drm_device *dev,
struct drm_plane *plane, enum omap_channel channel, int id);
+void omap_crtc_flush(struct drm_crtc *crtc);
struct drm_plane *omap_plane_init(struct drm_device *dev,
int plane_id, bool private_plane);
diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c
index d2b8c49bfb4a..8b019602ffe6 100644
--- a/drivers/gpu/drm/omapdrm/omap_fb.c
+++ b/drivers/gpu/drm/omapdrm/omap_fb.c
@@ -218,6 +218,20 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb,
info->rotation_type = OMAP_DSS_ROT_TILER;
info->screen_width = omap_gem_tiled_stride(plane->bo, orient);
} else {
+ switch (win->rotation & 0xf) {
+ case 0:
+ case BIT(DRM_ROTATE_0):
+ /* OK */
+ break;
+
+ default:
+ dev_warn(fb->dev->dev,
+ "rotation '%d' ignored for non-tiled fb\n",
+ win->rotation);
+ win->rotation = 0;
+ break;
+ }
+
info->paddr = get_linear_addr(plane, format, 0, x, y);
info->rotation_type = OMAP_DSS_ROT_DMA;
info->screen_width = plane->pitch;
diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c
index 002988d09021..1388ca7f87e8 100644
--- a/drivers/gpu/drm/omapdrm/omap_fbdev.c
+++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c
@@ -371,6 +371,9 @@ void omap_fbdev_free(struct drm_device *dev)
fbdev = to_omap_fbdev(priv->fbdev);
+ /* release the ref taken in omap_fbdev_create() */
+ omap_gem_put_paddr(fbdev->bo);
+
/* this will free the backing object */
if (fbdev->fb) {
drm_framebuffer_unregister_private(fbdev->fb);
diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c
index c8d972763889..95dbce286a41 100644
--- a/drivers/gpu/drm/omapdrm/omap_gem.c
+++ b/drivers/gpu/drm/omapdrm/omap_gem.c
@@ -980,12 +980,9 @@ int omap_gem_resume(struct device *dev)
#ifdef CONFIG_DEBUG_FS
void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
{
- struct drm_device *dev = obj->dev;
struct omap_gem_object *omap_obj = to_omap_bo(obj);
uint64_t off;
- WARN_ON(!mutex_is_locked(&dev->struct_mutex));
-
off = drm_vma_node_start(&obj->vma_node);
seq_printf(m, "%08x: %2d (%2d) %08llx %08Zx (%2d) %p %4d",
@@ -1050,10 +1047,10 @@ static inline bool is_waiting(struct omap_gem_sync_waiter *waiter)
{
struct omap_gem_object *omap_obj = waiter->omap_obj;
if ((waiter->op & OMAP_GEM_READ) &&
- (omap_obj->sync->read_complete < waiter->read_target))
+ (omap_obj->sync->write_complete < waiter->write_target))
return true;
if ((waiter->op & OMAP_GEM_WRITE) &&
- (omap_obj->sync->write_complete < waiter->write_target))
+ (omap_obj->sync->read_complete < waiter->read_target))
return true;
return false;
}
@@ -1229,6 +1226,8 @@ int omap_gem_op_async(struct drm_gem_object *obj, enum omap_gem_op op,
}
spin_unlock(&sync_lock);
+
+ kfree(waiter);
}
/* no waiting.. */
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c
index 046d5e660c04..3cf31ee59aac 100644
--- a/drivers/gpu/drm/omapdrm/omap_plane.c
+++ b/drivers/gpu/drm/omapdrm/omap_plane.c
@@ -225,6 +225,11 @@ int omap_plane_mode_set(struct drm_plane *plane,
omap_plane->apply_done_cb.arg = arg;
}
+ if (plane->fb)
+ drm_framebuffer_unreference(plane->fb);
+
+ drm_framebuffer_reference(fb);
+
plane->fb = fb;
plane->crtc = crtc;
@@ -241,10 +246,13 @@ static int omap_plane_update(struct drm_plane *plane,
struct omap_plane *omap_plane = to_omap_plane(plane);
omap_plane->enabled = true;
- if (plane->fb)
- drm_framebuffer_unreference(plane->fb);
-
- drm_framebuffer_reference(fb);
+ /* omap_plane_mode_set() takes adjusted src */
+ switch (omap_plane->win.rotation & 0xf) {
+ case BIT(DRM_ROTATE_90):
+ case BIT(DRM_ROTATE_270):
+ swap(src_w, src_h);
+ break;
+ }
return omap_plane_mode_set(plane, crtc, fb,
crtc_x, crtc_y, crtc_w, crtc_h,
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index fb187c78978f..c31c12b4e666 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -1177,27 +1177,43 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
/* Set NUM_BANKS. */
if (rdev->family >= CHIP_TAHITI) {
- unsigned tileb, index, num_banks, tile_split_bytes;
+ unsigned index, num_banks;
- /* Calculate the macrotile mode index. */
- tile_split_bytes = 64 << tile_split;
- tileb = 8 * 8 * target_fb->bits_per_pixel / 8;
- tileb = min(tile_split_bytes, tileb);
+ if (rdev->family >= CHIP_BONAIRE) {
+ unsigned tileb, tile_split_bytes;
- for (index = 0; tileb > 64; index++) {
- tileb >>= 1;
- }
+ /* Calculate the macrotile mode index. */
+ tile_split_bytes = 64 << tile_split;
+ tileb = 8 * 8 * target_fb->bits_per_pixel / 8;
+ tileb = min(tile_split_bytes, tileb);
- if (index >= 16) {
- DRM_ERROR("Wrong screen bpp (%u) or tile split (%u)\n",
- target_fb->bits_per_pixel, tile_split);
- return -EINVAL;
- }
+ for (index = 0; tileb > 64; index++)
+ tileb >>= 1;
+
+ if (index >= 16) {
+ DRM_ERROR("Wrong screen bpp (%u) or tile split (%u)\n",
+ target_fb->bits_per_pixel, tile_split);
+ return -EINVAL;
+ }
- if (rdev->family >= CHIP_BONAIRE)
num_banks = (rdev->config.cik.macrotile_mode_array[index] >> 6) & 0x3;
- else
+ } else {
+ switch (target_fb->bits_per_pixel) {
+ case 8:
+ index = 10;
+ break;
+ case 16:
+ index = SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP;
+ break;
+ default:
+ case 32:
+ index = SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP;
+ break;
+ }
+
num_banks = (rdev->config.si.tile_mode_array[index] >> 20) & 0x3;
+ }
+
fb_format |= EVERGREEN_GRPH_NUM_BANKS(num_banks);
} else {
/* NI and older. */
@@ -1720,8 +1736,9 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
}
/* otherwise, pick one of the plls */
if ((rdev->family == CHIP_KAVERI) ||
- (rdev->family == CHIP_KABINI)) {
- /* KB/KV has PPLL1 and PPLL2 */
+ (rdev->family == CHIP_KABINI) ||
+ (rdev->family == CHIP_MULLINS)) {
+ /* KB/KV/ML has PPLL1 and PPLL2 */
pll_in_use = radeon_get_pll_use_mask(crtc);
if (!(pll_in_use & (1 << ATOM_PPLL2)))
return ATOM_PPLL2;
@@ -1885,6 +1902,9 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc,
(ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
is_tvcv = true;
+ if (!radeon_crtc->adjusted_clock)
+ return -EINVAL;
+
atombios_crtc_set_pll(crtc, adjusted_mode);
if (ASIC_IS_DCE4(rdev))
diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c
index 8b0ab170cef9..54e4f52549af 100644
--- a/drivers/gpu/drm/radeon/atombios_dp.c
+++ b/drivers/gpu/drm/radeon/atombios_dp.c
@@ -142,7 +142,8 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,
return recv_bytes;
}
-#define HEADER_SIZE 4
+#define BARE_ADDRESS_SIZE 3
+#define HEADER_SIZE (BARE_ADDRESS_SIZE + 1)
static ssize_t
radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
@@ -160,13 +161,19 @@ radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
tx_buf[0] = msg->address & 0xff;
tx_buf[1] = msg->address >> 8;
tx_buf[2] = msg->request << 4;
- tx_buf[3] = msg->size - 1;
+ tx_buf[3] = msg->size ? (msg->size - 1) : 0;
switch (msg->request & ~DP_AUX_I2C_MOT) {
case DP_AUX_NATIVE_WRITE:
case DP_AUX_I2C_WRITE:
+ /* tx_size needs to be 4 even for bare address packets since the atom
+ * table needs the info in tx_buf[3].
+ */
tx_size = HEADER_SIZE + msg->size;
- tx_buf[3] |= tx_size << 4;
+ if (msg->size == 0)
+ tx_buf[3] |= BARE_ADDRESS_SIZE << 4;
+ else
+ tx_buf[3] |= tx_size << 4;
memcpy(tx_buf + HEADER_SIZE, msg->buffer, msg->size);
ret = radeon_process_aux_ch(chan,
tx_buf, tx_size, NULL, 0, delay, &ack);
@@ -176,8 +183,14 @@ radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
break;
case DP_AUX_NATIVE_READ:
case DP_AUX_I2C_READ:
+ /* tx_size needs to be 4 even for bare address packets since the atom
+ * table needs the info in tx_buf[3].
+ */
tx_size = HEADER_SIZE;
- tx_buf[3] |= tx_size << 4;
+ if (msg->size == 0)
+ tx_buf[3] |= BARE_ADDRESS_SIZE << 4;
+ else
+ tx_buf[3] |= tx_size << 4;
ret = radeon_process_aux_ch(chan,
tx_buf, tx_size, msg->buffer, msg->size, delay, &ack);
break;
@@ -186,7 +199,7 @@ radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
break;
}
- if (ret > 0)
+ if (ret >= 0)
msg->reply = ack >> 4;
return ret;
@@ -194,98 +207,16 @@ radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
void radeon_dp_aux_init(struct radeon_connector *radeon_connector)
{
- struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
-
- dig_connector->dp_i2c_bus->aux.dev = radeon_connector->base.kdev;
- dig_connector->dp_i2c_bus->aux.transfer = radeon_dp_aux_transfer;
-}
-
-int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
- u8 write_byte, u8 *read_byte)
-{
- struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
- struct radeon_i2c_chan *auxch = i2c_get_adapdata(adapter);
- u16 address = algo_data->address;
- u8 msg[5];
- u8 reply[2];
- unsigned retry;
- int msg_bytes;
- int reply_bytes = 1;
int ret;
- u8 ack;
- /* Set up the address */
- msg[0] = address;
- msg[1] = address >> 8;
+ radeon_connector->ddc_bus->rec.hpd = radeon_connector->hpd.hpd;
+ radeon_connector->ddc_bus->aux.dev = radeon_connector->base.kdev;
+ radeon_connector->ddc_bus->aux.transfer = radeon_dp_aux_transfer;
+ ret = drm_dp_aux_register_i2c_bus(&radeon_connector->ddc_bus->aux);
+ if (!ret)
+ radeon_connector->ddc_bus->has_aux = true;
- /* Set up the command byte */
- if (mode & MODE_I2C_READ) {
- msg[2] = DP_AUX_I2C_READ << 4;
- msg_bytes = 4;
- msg[3] = msg_bytes << 4;
- } else {
- msg[2] = DP_AUX_I2C_WRITE << 4;
- msg_bytes = 5;
- msg[3] = msg_bytes << 4;
- msg[4] = write_byte;
- }
-
- /* special handling for start/stop */
- if (mode & (MODE_I2C_START | MODE_I2C_STOP))
- msg[3] = 3 << 4;
-
- /* Set MOT bit for all but stop */
- if ((mode & MODE_I2C_STOP) == 0)
- msg[2] |= DP_AUX_I2C_MOT << 4;
-
- for (retry = 0; retry < 7; retry++) {
- ret = radeon_process_aux_ch(auxch,
- msg, msg_bytes, reply, reply_bytes, 0, &ack);
- if (ret == -EBUSY)
- continue;
- else if (ret < 0) {
- DRM_DEBUG_KMS("aux_ch failed %d\n", ret);
- return ret;
- }
-
- switch ((ack >> 4) & DP_AUX_NATIVE_REPLY_MASK) {
- case DP_AUX_NATIVE_REPLY_ACK:
- /* I2C-over-AUX Reply field is only valid
- * when paired with AUX ACK.
- */
- break;
- case DP_AUX_NATIVE_REPLY_NACK:
- DRM_DEBUG_KMS("aux_ch native nack\n");
- return -EREMOTEIO;
- case DP_AUX_NATIVE_REPLY_DEFER:
- DRM_DEBUG_KMS("aux_ch native defer\n");
- usleep_range(500, 600);
- continue;
- default:
- DRM_ERROR("aux_ch invalid native reply 0x%02x\n", ack);
- return -EREMOTEIO;
- }
-
- switch ((ack >> 4) & DP_AUX_I2C_REPLY_MASK) {
- case DP_AUX_I2C_REPLY_ACK:
- if (mode == MODE_I2C_READ)
- *read_byte = reply[0];
- return ret;
- case DP_AUX_I2C_REPLY_NACK:
- DRM_DEBUG_KMS("aux_i2c nack\n");
- return -EREMOTEIO;
- case DP_AUX_I2C_REPLY_DEFER:
- DRM_DEBUG_KMS("aux_i2c defer\n");
- usleep_range(400, 500);
- break;
- default:
- DRM_ERROR("aux_i2c invalid reply 0x%02x\n", ack);
- return -EREMOTEIO;
- }
- }
-
- DRM_DEBUG_KMS("aux i2c too many retries, giving up\n");
- return -EREMOTEIO;
+ WARN(ret, "drm_dp_aux_register_i2c_bus() failed with error %d\n", ret);
}
/***** general DP utility functions *****/
@@ -420,12 +351,11 @@ static u8 radeon_dp_encoder_service(struct radeon_device *rdev,
u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector)
{
- struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
struct drm_device *dev = radeon_connector->base.dev;
struct radeon_device *rdev = dev->dev_private;
return radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_GET_SINK_TYPE, 0,
- dig_connector->dp_i2c_bus->rec.i2c_id, 0);
+ radeon_connector->ddc_bus->rec.i2c_id, 0);
}
static void radeon_dp_probe_oui(struct radeon_connector *radeon_connector)
@@ -436,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(&dig_connector->dp_i2c_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(&dig_connector->dp_i2c_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]);
}
@@ -451,7 +381,7 @@ bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector)
u8 msg[DP_DPCD_SIZE];
int ret, i;
- ret = drm_dp_dpcd_read(&dig_connector->dp_i2c_bus->aux, DP_DPCD_REV, msg,
+ ret = drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_DPCD_REV, msg,
DP_DPCD_SIZE);
if (ret > 0) {
memcpy(dig_connector->dpcd, msg, DP_DPCD_SIZE);
@@ -489,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(&dig_connector->dp_i2c_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(&dig_connector->dp_i2c_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;
@@ -554,7 +486,8 @@ bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector)
u8 link_status[DP_LINK_STATUS_SIZE];
struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;
- if (drm_dp_dpcd_read_link_status(&dig->dp_i2c_bus->aux, link_status) <= 0)
+ if (drm_dp_dpcd_read_link_status(&radeon_connector->ddc_bus->aux, link_status)
+ <= 0)
return false;
if (drm_dp_channel_eq_ok(link_status, dig->dp_lane_count))
return false;
@@ -574,7 +507,7 @@ void radeon_dp_set_rx_power_state(struct drm_connector *connector,
/* power up/down the sink */
if (dig_connector->dpcd[0] >= 0x11) {
- drm_dp_dpcd_writeb(&dig_connector->dp_i2c_bus->aux,
+ drm_dp_dpcd_writeb(&radeon_connector->ddc_bus->aux,
DP_SET_POWER, power_state);
usleep_range(1000, 2000);
}
@@ -878,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(&dig_connector->dp_i2c_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;
@@ -890,7 +827,7 @@ void radeon_dp_link_train(struct drm_encoder *encoder,
dp_info.connector = connector;
dp_info.dp_lane_count = dig_connector->dp_lane_count;
dp_info.dp_clock = dig_connector->dp_clock;
- dp_info.aux = &dig_connector->dp_i2c_bus->aux;
+ dp_info.aux = &radeon_connector->ddc_bus->aux;
if (radeon_dp_link_train_init(&dp_info))
goto done;
diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c
index cad89a977527..10dae4106c08 100644
--- a/drivers/gpu/drm/radeon/ci_dpm.c
+++ b/drivers/gpu/drm/radeon/ci_dpm.c
@@ -21,8 +21,10 @@
*
*/
+#include <linux/firmware.h>
#include "drmP.h"
#include "radeon.h"
+#include "radeon_ucode.h"
#include "cikd.h"
#include "r600_dpm.h"
#include "ci_dpm.h"
@@ -202,24 +204,29 @@ static void ci_initialize_powertune_defaults(struct radeon_device *rdev)
struct ci_power_info *pi = ci_get_pi(rdev);
switch (rdev->pdev->device) {
+ case 0x6649:
case 0x6650:
+ case 0x6651:
case 0x6658:
case 0x665C:
+ case 0x665D:
default:
pi->powertune_defaults = &defaults_bonaire_xt;
break;
- case 0x6651:
- case 0x665D:
- pi->powertune_defaults = &defaults_bonaire_pro;
- break;
case 0x6640:
- pi->powertune_defaults = &defaults_saturn_xt;
- break;
case 0x6641:
- pi->powertune_defaults = &defaults_saturn_pro;
+ case 0x6646:
+ case 0x6647:
+ pi->powertune_defaults = &defaults_saturn_xt;
break;
case 0x67B8:
case 0x67B0:
+ pi->powertune_defaults = &defaults_hawaii_xt;
+ break;
+ case 0x67BA:
+ case 0x67B1:
+ pi->powertune_defaults = &defaults_hawaii_pro;
+ break;
case 0x67A0:
case 0x67A1:
case 0x67A2:
@@ -228,11 +235,7 @@ static void ci_initialize_powertune_defaults(struct radeon_device *rdev)
case 0x67AA:
case 0x67B9:
case 0x67BE:
- pi->powertune_defaults = &defaults_hawaii_xt;
- break;
- case 0x67BA:
- case 0x67B1:
- pi->powertune_defaults = &defaults_hawaii_pro;
+ pi->powertune_defaults = &defaults_bonaire_xt;
break;
}
@@ -5146,6 +5149,12 @@ int ci_dpm_init(struct radeon_device *rdev)
pi->mclk_dpm_key_disabled = 0;
pi->pcie_dpm_key_disabled = 0;
+ /* mclk dpm is unstable on some R7 260X cards with the old mc ucode */
+ if ((rdev->pdev->device == 0x6658) &&
+ (rdev->mc_fw->size == (BONAIRE_MC_UCODE_SIZE * 4))) {
+ pi->mclk_dpm_key_disabled = 1;
+ }
+
pi->caps_sclk_ds = true;
pi->mclk_strobe_mode_threshold = 40000;
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index 745143c2358f..d2fd98968085 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -38,6 +38,7 @@ MODULE_FIRMWARE("radeon/BONAIRE_me.bin");
MODULE_FIRMWARE("radeon/BONAIRE_ce.bin");
MODULE_FIRMWARE("radeon/BONAIRE_mec.bin");
MODULE_FIRMWARE("radeon/BONAIRE_mc.bin");
+MODULE_FIRMWARE("radeon/BONAIRE_mc2.bin");
MODULE_FIRMWARE("radeon/BONAIRE_rlc.bin");
MODULE_FIRMWARE("radeon/BONAIRE_sdma.bin");
MODULE_FIRMWARE("radeon/BONAIRE_smc.bin");
@@ -46,6 +47,7 @@ MODULE_FIRMWARE("radeon/HAWAII_me.bin");
MODULE_FIRMWARE("radeon/HAWAII_ce.bin");
MODULE_FIRMWARE("radeon/HAWAII_mec.bin");
MODULE_FIRMWARE("radeon/HAWAII_mc.bin");
+MODULE_FIRMWARE("radeon/HAWAII_mc2.bin");
MODULE_FIRMWARE("radeon/HAWAII_rlc.bin");
MODULE_FIRMWARE("radeon/HAWAII_sdma.bin");
MODULE_FIRMWARE("radeon/HAWAII_smc.bin");
@@ -61,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);
@@ -1471,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) {
@@ -1502,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,
@@ -1703,20 +1762,20 @@ int ci_mc_load_microcode(struct radeon_device *rdev)
const __be32 *fw_data;
u32 running, blackout = 0;
u32 *io_mc_regs;
- int i, ucode_size, regs_size;
+ int i, regs_size, ucode_size;
if (!rdev->mc_fw)
return -EINVAL;
+ ucode_size = rdev->mc_fw->size / 4;
+
switch (rdev->family) {
case CHIP_BONAIRE:
io_mc_regs = (u32 *)&bonaire_io_mc_regs;
- ucode_size = CIK_MC_UCODE_SIZE;
regs_size = BONAIRE_IO_MC_REGS_SIZE;
break;
case CHIP_HAWAII:
io_mc_regs = (u32 *)&hawaii_io_mc_regs;
- ucode_size = HAWAII_MC_UCODE_SIZE;
regs_size = HAWAII_IO_MC_REGS_SIZE;
break;
default:
@@ -1783,7 +1842,7 @@ static int cik_init_microcode(struct radeon_device *rdev)
const char *chip_name;
size_t pfp_req_size, me_req_size, ce_req_size,
mec_req_size, rlc_req_size, mc_req_size = 0,
- sdma_req_size, smc_req_size = 0;
+ sdma_req_size, smc_req_size = 0, mc2_req_size = 0;
char fw_name[30];
int err;
@@ -1797,7 +1856,8 @@ static int cik_init_microcode(struct radeon_device *rdev)
ce_req_size = CIK_CE_UCODE_SIZE * 4;
mec_req_size = CIK_MEC_UCODE_SIZE * 4;
rlc_req_size = BONAIRE_RLC_UCODE_SIZE * 4;
- mc_req_size = CIK_MC_UCODE_SIZE * 4;
+ mc_req_size = BONAIRE_MC_UCODE_SIZE * 4;
+ mc2_req_size = BONAIRE_MC2_UCODE_SIZE * 4;
sdma_req_size = CIK_SDMA_UCODE_SIZE * 4;
smc_req_size = ALIGN(BONAIRE_SMC_UCODE_SIZE, 4);
break;
@@ -1809,6 +1869,7 @@ static int cik_init_microcode(struct radeon_device *rdev)
mec_req_size = CIK_MEC_UCODE_SIZE * 4;
rlc_req_size = BONAIRE_RLC_UCODE_SIZE * 4;
mc_req_size = HAWAII_MC_UCODE_SIZE * 4;
+ mc2_req_size = HAWAII_MC2_UCODE_SIZE * 4;
sdma_req_size = CIK_SDMA_UCODE_SIZE * 4;
smc_req_size = ALIGN(HAWAII_SMC_UCODE_SIZE, 4);
break;
@@ -1830,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();
}
@@ -1904,16 +1974,22 @@ static int cik_init_microcode(struct radeon_device *rdev)
/* No SMC, MC ucode on APUs */
if (!(rdev->flags & RADEON_IS_IGP)) {
- snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name);
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc2.bin", chip_name);
err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev);
- if (err)
- goto out;
- if (rdev->mc_fw->size != mc_req_size) {
+ if (err) {
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name);
+ err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev);
+ if (err)
+ goto out;
+ }
+ if ((rdev->mc_fw->size != mc_req_size) &&
+ (rdev->mc_fw->size != mc2_req_size)){
printk(KERN_ERR
"cik_mc: Bogus length %zu in firmware \"%s\"\n",
rdev->mc_fw->size, fw_name);
err = -EINVAL;
}
+ DRM_INFO("%s: %zu bytes\n", fw_name, rdev->mc_fw->size);
snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", chip_name);
err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev);
@@ -3262,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;
@@ -3692,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;
}
@@ -5790,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);
@@ -6538,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;
@@ -6683,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);
@@ -7039,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);
@@ -7075,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)
@@ -7085,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)
@@ -7096,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)
@@ -7447,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:
diff --git a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c
index 89b4afa5041c..72e464c79a88 100644
--- a/drivers/gpu/drm/radeon/cik_sdma.c
+++ b/drivers/gpu/drm/radeon/cik_sdma.c
@@ -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;
}
@@ -597,7 +598,7 @@ int cik_sdma_ring_test(struct radeon_device *rdev,
tmp = 0xCAFEDEAD;
writel(tmp, ptr);
- r = radeon_ring_lock(rdev, ring, 4);
+ r = radeon_ring_lock(rdev, ring, 5);
if (r) {
DRM_ERROR("radeon: dma failed to lock ring %d (%d).\n", ring->idx, r);
return r;
diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h
index 213873270d5f..dd7926394a8f 100644
--- a/drivers/gpu/drm/radeon/cikd.h
+++ b/drivers/gpu/drm/radeon/cikd.h
@@ -888,6 +888,15 @@
# 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
diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c
index 94e858751994..0a65dc7e93e7 100644
--- a/drivers/gpu/drm/radeon/dce6_afmt.c
+++ b/drivers/gpu/drm/radeon/dce6_afmt.c
@@ -309,11 +309,17 @@ int dce6_audio_init(struct radeon_device *rdev)
rdev->audio.enabled = true;
- if (ASIC_IS_DCE8(rdev))
+ if (ASIC_IS_DCE81(rdev)) /* KV: 4 streams, 7 endpoints */
+ rdev->audio.num_pins = 7;
+ else if (ASIC_IS_DCE83(rdev)) /* KB: 2 streams, 3 endpoints */
+ rdev->audio.num_pins = 3;
+ else if (ASIC_IS_DCE8(rdev)) /* BN/HW: 6 streams, 7 endpoints */
+ rdev->audio.num_pins = 7;
+ else if (ASIC_IS_DCE61(rdev)) /* TN: 4 streams, 6 endpoints */
rdev->audio.num_pins = 6;
- else if (ASIC_IS_DCE61(rdev))
- rdev->audio.num_pins = 4;
- else
+ else if (ASIC_IS_DCE64(rdev)) /* OL: 2 streams, 2 endpoints */
+ rdev->audio.num_pins = 2;
+ else /* SI: 6 streams, 6 endpoints */
rdev->audio.num_pins = 6;
for (i = 0; i < rdev->audio.num_pins; i++) {
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index b406546440da..0f7a51a3694f 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -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:
diff --git a/drivers/gpu/drm/radeon/evergreen_dma.c b/drivers/gpu/drm/radeon/evergreen_dma.c
index 287fe966d7de..478caefe0fef 100644
--- a/drivers/gpu/drm/radeon/evergreen_dma.c
+++ b/drivers/gpu/drm/radeon/evergreen_dma.c
@@ -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;
}
diff --git a/drivers/gpu/drm/radeon/kv_dpm.c b/drivers/gpu/drm/radeon/kv_dpm.c
index 16ec9d56a234..3f6e817d97ee 100644
--- a/drivers/gpu/drm/radeon/kv_dpm.c
+++ b/drivers/gpu/drm/radeon/kv_dpm.c
@@ -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;
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index 6e887d004eba..bbc189fd3ddc 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -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:
diff --git a/drivers/gpu/drm/radeon/r600_dma.c b/drivers/gpu/drm/radeon/r600_dma.c
index 53fcb28f5578..4969cef44a19 100644
--- a/drivers/gpu/drm/radeon/r600_dma.c
+++ b/drivers/gpu/drm/radeon/r600_dma.c
@@ -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;
}
diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c
index cbf7e3269f84..9c61b74ef441 100644
--- a/drivers/gpu/drm/radeon/r600_dpm.c
+++ b/drivers/gpu/drm/radeon/r600_dpm.c
@@ -158,16 +158,18 @@ u32 r600_dpm_get_vblank_time(struct radeon_device *rdev)
u32 line_time_us, vblank_lines;
u32 vblank_time_us = 0xffffffff; /* if the displays are off, vblank time is max */
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
- radeon_crtc = to_radeon_crtc(crtc);
- if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) {
- line_time_us = (radeon_crtc->hw_mode.crtc_htotal * 1000) /
- radeon_crtc->hw_mode.clock;
- vblank_lines = radeon_crtc->hw_mode.crtc_vblank_end -
- radeon_crtc->hw_mode.crtc_vdisplay +
- (radeon_crtc->v_border * 2);
- vblank_time_us = vblank_lines * line_time_us;
- break;
+ if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) {
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ radeon_crtc = to_radeon_crtc(crtc);
+ if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) {
+ line_time_us = (radeon_crtc->hw_mode.crtc_htotal * 1000) /
+ radeon_crtc->hw_mode.clock;
+ vblank_lines = radeon_crtc->hw_mode.crtc_vblank_end -
+ radeon_crtc->hw_mode.crtc_vdisplay +
+ (radeon_crtc->v_border * 2);
+ vblank_time_us = vblank_lines * line_time_us;
+ break;
+ }
}
}
@@ -181,14 +183,15 @@ u32 r600_dpm_get_vrefresh(struct radeon_device *rdev)
struct radeon_crtc *radeon_crtc;
u32 vrefresh = 0;
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
- radeon_crtc = to_radeon_crtc(crtc);
- if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) {
- vrefresh = radeon_crtc->hw_mode.vrefresh;
- break;
+ if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) {
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ radeon_crtc = to_radeon_crtc(crtc);
+ if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) {
+ vrefresh = radeon_crtc->hw_mode.vrefresh;
+ break;
+ }
}
}
-
return vrefresh;
}
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index f21db7a0b34d..8149e7cf4303 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -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 {
@@ -739,7 +745,7 @@ union radeon_irq_stat_regs {
struct cik_irq_stat_regs cik;
};
-#define RADEON_MAX_HPD_PINS 6
+#define RADEON_MAX_HPD_PINS 7
#define RADEON_MAX_CRTCS 6
#define RADEON_MAX_AFMT_BLOCKS 7
@@ -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,
@@ -2321,6 +2328,7 @@ struct radeon_device {
bool have_disp_power_ref;
};
+bool radeon_is_px(struct drm_device *dev);
int radeon_device_init(struct radeon_device *rdev,
struct drm_device *ddev,
struct pci_dev *pdev,
@@ -2631,6 +2639,10 @@ void r100_pll_errata_after_index(struct radeon_device *rdev);
#define ASIC_IS_DCE64(rdev) ((rdev->family == CHIP_OLAND))
#define ASIC_IS_NODCE(rdev) ((rdev->family == CHIP_HAINAN))
#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) || \
+ (rdev->family == CHIP_MULLINS))
#define ASIC_IS_LOMBOK(rdev) ((rdev->ddev->pdev->device == 0x6849) || \
(rdev->ddev->pdev->device == 0x6850) || \
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
index b8a24a75d4ff..be20e62dac83 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -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) {
diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
index fa9a9c02751e..a9fb0d016d38 100644
--- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c
+++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
@@ -59,7 +59,7 @@ struct atpx_mux {
u16 mux;
} __packed;
-bool radeon_is_px(void) {
+bool radeon_has_atpx(void) {
return radeon_atpx_priv.atpx_detected;
}
@@ -528,6 +528,13 @@ static bool radeon_atpx_detect(void)
has_atpx |= (radeon_atpx_pci_probe_handle(pdev) == true);
}
+ /* some newer PX laptops mark the dGPU as a non-VGA display device */
+ while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) {
+ vga_count++;
+
+ has_atpx |= (radeon_atpx_pci_probe_handle(pdev) == true);
+ }
+
if (has_atpx && vga_count == 2) {
acpi_get_name(radeon_atpx_priv.atpx.handle, ACPI_FULL_PATHNAME, &buffer);
printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n",
diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c
index b3633d9a5317..9ab30976287d 100644
--- a/drivers/gpu/drm/radeon/radeon_bios.c
+++ b/drivers/gpu/drm/radeon/radeon_bios.c
@@ -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;
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index c566b486ca08..ea50e0ae7bf7 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -1261,21 +1261,6 @@ static const struct drm_connector_funcs radeon_dvi_connector_funcs = {
.force = radeon_dvi_force,
};
-static void radeon_dp_connector_destroy(struct drm_connector *connector)
-{
- struct radeon_connector *radeon_connector = to_radeon_connector(connector);
- struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
-
- if (radeon_connector->edid)
- kfree(radeon_connector->edid);
- if (radeon_dig_connector->dp_i2c_bus)
- radeon_i2c_destroy(radeon_dig_connector->dp_i2c_bus);
- kfree(radeon_connector->con_priv);
- drm_sysfs_connector_remove(connector);
- drm_connector_cleanup(connector);
- kfree(connector);
-}
-
static int radeon_dp_get_modes(struct drm_connector *connector)
{
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
@@ -1553,7 +1538,7 @@ static const struct drm_connector_funcs radeon_dp_connector_funcs = {
.detect = radeon_dp_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.set_property = radeon_connector_set_property,
- .destroy = radeon_dp_connector_destroy,
+ .destroy = radeon_connector_destroy,
.force = radeon_dvi_force,
};
@@ -1562,7 +1547,7 @@ static const struct drm_connector_funcs radeon_edp_connector_funcs = {
.detect = radeon_dp_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.set_property = radeon_lvds_set_property,
- .destroy = radeon_dp_connector_destroy,
+ .destroy = radeon_connector_destroy,
.force = radeon_dvi_force,
};
@@ -1571,7 +1556,7 @@ static const struct drm_connector_funcs radeon_lvds_bridge_connector_funcs = {
.detect = radeon_dp_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.set_property = radeon_lvds_set_property,
- .destroy = radeon_dp_connector_destroy,
+ .destroy = radeon_connector_destroy,
.force = radeon_dvi_force,
};
@@ -1668,17 +1653,10 @@ radeon_add_atom_connector(struct drm_device *dev,
radeon_dig_connector->igp_lane_info = igp_lane_info;
radeon_connector->con_priv = radeon_dig_connector;
if (i2c_bus->valid) {
- /* add DP i2c bus */
- if (connector_type == DRM_MODE_CONNECTOR_eDP)
- radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "eDP-auxch");
- else
- radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch");
- if (radeon_dig_connector->dp_i2c_bus)
+ radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
+ if (radeon_connector->ddc_bus)
has_aux = true;
else
- DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n");
- radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
- if (!radeon_connector->ddc_bus)
DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
}
switch (connector_type) {
@@ -1893,10 +1871,6 @@ radeon_add_atom_connector(struct drm_device *dev,
drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type);
drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs);
if (i2c_bus->valid) {
- /* add DP i2c bus */
- radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch");
- if (!radeon_dig_connector->dp_i2c_bus)
- DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n");
radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
if (radeon_connector->ddc_bus)
has_aux = true;
@@ -1942,14 +1916,10 @@ radeon_add_atom_connector(struct drm_device *dev,
drm_connector_init(dev, &radeon_connector->base, &radeon_edp_connector_funcs, connector_type);
drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs);
if (i2c_bus->valid) {
- /* add DP i2c bus */
- radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "eDP-auxch");
- if (radeon_dig_connector->dp_i2c_bus)
+ radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
+ if (radeon_connector->ddc_bus)
has_aux = true;
else
- DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n");
- radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
- if (!radeon_connector->ddc_bus)
DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
}
drm_object_attach_property(&radeon_connector->base.base,
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c
index 2b6e0ebcc13a..41ecf8a60611 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -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;
+ }
}
}
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 835516d2d257..14671406212f 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -99,14 +99,18 @@ static const char radeon_family_name[][16] = {
"KAVERI",
"KABINI",
"HAWAII",
+ "MULLINS",
"LAST",
};
-#if defined(CONFIG_VGA_SWITCHEROO)
-bool radeon_is_px(void);
-#else
-static inline bool radeon_is_px(void) { return false; }
-#endif
+bool radeon_is_px(struct drm_device *dev)
+{
+ struct radeon_device *rdev = dev->dev_private;
+
+ if (rdev->flags & RADEON_IS_PX)
+ return true;
+ return false;
+}
/**
* radeon_program_register_sequence - program an array of registers.
@@ -1082,7 +1086,7 @@ static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero
{
struct drm_device *dev = pci_get_drvdata(pdev);
- if (radeon_is_px() && state == VGA_SWITCHEROO_OFF)
+ if (radeon_is_px(dev) && state == VGA_SWITCHEROO_OFF)
return;
if (state == VGA_SWITCHEROO_ON) {
@@ -1301,9 +1305,7 @@ int radeon_device_init(struct radeon_device *rdev,
* ignore it */
vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode);
- if (radeon_runtime_pm == 1)
- runtime = true;
- if ((radeon_runtime_pm == -1) && radeon_is_px())
+ if (rdev->flags & RADEON_IS_PX)
runtime = true;
vga_switcheroo_register_client(rdev->pdev, &radeon_switcheroo_ops, runtime);
if (runtime)
@@ -1531,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);
@@ -1560,6 +1557,12 @@ int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon)
}
drm_kms_helper_poll_enable(dev);
+
+ if (fbcon) {
+ radeon_fbdev_set_suspend(rdev, 0);
+ console_unlock();
+ }
+
return 0;
}
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 386cfa4c194d..356b733caafe 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -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 ||
@@ -759,19 +763,18 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
if (radeon_connector_encoder_get_dp_bridge_encoder_id(&radeon_connector->base) !=
ENCODER_OBJECT_ID_NONE) {
- struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;
-
- if (dig->dp_i2c_bus)
+ if (radeon_connector->ddc_bus->has_aux)
radeon_connector->edid = drm_get_edid(&radeon_connector->base,
- &dig->dp_i2c_bus->adapter);
+ &radeon_connector->ddc_bus->aux.ddc);
} else if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
(radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) {
struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;
if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT ||
- dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) && dig->dp_i2c_bus)
+ dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) &&
+ radeon_connector->ddc_bus->has_aux)
radeon_connector->edid = drm_get_edid(&radeon_connector->base,
- &dig->dp_i2c_bus->adapter);
+ &radeon_connector->ddc_bus->aux.ddc);
else if (radeon_connector->ddc_bus && !radeon_connector->edid)
radeon_connector->edid = drm_get_edid(&radeon_connector->base,
&radeon_connector->ddc_bus->adapter);
@@ -827,20 +830,52 @@ 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;
}
}
/**
+ * avivo_get_fb_ref_div - feedback and ref divider calculation
+ *
+ * @nom: nominator
+ * @den: denominator
+ * @post_div: post divider
+ * @fb_div_max: feedback divider maximum
+ * @ref_div_max: reference divider maximum
+ * @fb_div: resulting feedback divider
+ * @ref_div: resulting reference divider
+ *
+ * Calculate feedback and reference divider for a given post divider. Makes
+ * sure we stay within the limits.
+ */
+static void avivo_get_fb_ref_div(unsigned nom, unsigned den, unsigned post_div,
+ unsigned fb_div_max, unsigned ref_div_max,
+ unsigned *fb_div, unsigned *ref_div)
+{
+ /* limit reference * post divider to a maximum */
+ 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);
+ *fb_div = DIV_ROUND_CLOSEST(nom * *ref_div * post_div, den);
+
+ /* limit fb divider to its maximum */
+ if (*fb_div > fb_div_max) {
+ *ref_div = DIV_ROUND_CLOSEST(*ref_div * fb_div_max, *fb_div);
+ *fb_div = fb_div_max;
+ }
+}
+
+/**
* radeon_compute_pll_avivo - compute PLL paramaters
*
* @pll: information about the PLL
@@ -861,11 +896,14 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll,
u32 *ref_div_p,
u32 *post_div_p)
{
+ unsigned target_clock = pll->flags & RADEON_PLL_USE_FRAC_FB_DIV ?
+ freq : freq / 10;
+
unsigned fb_div_min, fb_div_max, fb_div;
unsigned post_div_min, post_div_max, post_div;
unsigned ref_div_min, ref_div_max, ref_div;
unsigned post_div_best, diff_best;
- unsigned nom, den, tmp;
+ unsigned nom, den;
/* determine allowed feedback divider range */
fb_div_min = pll->min_feedback_div;
@@ -881,14 +919,18 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll,
ref_div_min = pll->reference_div;
else
ref_div_min = pll->min_ref_div;
- ref_div_max = pll->max_ref_div;
+
+ if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV &&
+ pll->flags & RADEON_PLL_USE_REF_DIV)
+ ref_div_max = pll->reference_div;
+ else
+ ref_div_max = pll->max_ref_div;
/* determine allowed post divider range */
if (pll->flags & RADEON_PLL_USE_POST_DIV) {
post_div_min = pll->post_div;
post_div_max = pll->post_div;
} else {
- unsigned target_clock = freq / 10;
unsigned vco_min, vco_max;
if (pll->flags & RADEON_PLL_IS_LCD) {
@@ -899,6 +941,11 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll,
vco_max = pll->pll_out_max;
}
+ if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) {
+ vco_min *= 10;
+ vco_max *= 10;
+ }
+
post_div_min = vco_min / target_clock;
if ((target_clock * post_div_min) < vco_min)
++post_div_min;
@@ -913,7 +960,7 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll,
}
/* represent the searched ratio as fractional number */
- nom = pll->flags & RADEON_PLL_USE_FRAC_FB_DIV ? freq : freq / 10;
+ nom = target_clock;
den = pll->reference_freq;
/* reduce the numbers to a simpler ratio */
@@ -927,7 +974,12 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll,
diff_best = ~0;
for (post_div = post_div_min; post_div <= post_div_max; ++post_div) {
- unsigned diff = abs(den - den / post_div * post_div);
+ unsigned diff;
+ avivo_get_fb_ref_div(nom, den, post_div, fb_div_max,
+ ref_div_max, &fb_div, &ref_div);
+ diff = abs(target_clock - (pll->reference_freq * fb_div) /
+ (ref_div * post_div));
+
if (diff < diff_best || (diff == diff_best &&
!(pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP))) {
@@ -937,29 +989,24 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll,
}
post_div = post_div_best;
- /* get matching reference and feedback divider */
- ref_div = max(den / post_div, 1u);
- fb_div = nom;
-
- /* we're almost done, but reference and feedback
- divider might be to large now */
-
- tmp = ref_div;
-
- if (fb_div > fb_div_max) {
- ref_div = ref_div * fb_div_max / fb_div;
- fb_div = fb_div_max;
- }
-
- if (ref_div > ref_div_max) {
- ref_div = ref_div_max;
- fb_div = nom * ref_div_max / tmp;
- }
+ /* get the feedback and reference divider for the optimal value */
+ avivo_get_fb_ref_div(nom, den, post_div, fb_div_max, ref_div_max,
+ &fb_div, &ref_div);
/* reduce the numbers to a simpler ratio once more */
/* 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;
@@ -976,7 +1023,7 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll,
*post_div_p = post_div;
DRM_DEBUG_KMS("%d - %d, pll dividers - fb: %d.%d ref: %d, post %d\n",
- freq, *dot_clock_p, *fb_div_p, *frac_fb_div_p,
+ freq, *dot_clock_p * 10, *fb_div_p, *frac_fb_div_p,
ref_div, post_div);
}
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index d0eba48dd74e..c00a2f585185 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -115,6 +115,7 @@ extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc,
unsigned int flags,
int *vpos, int *hpos, ktime_t *stime,
ktime_t *etime);
+extern bool radeon_is_px(struct drm_device *dev);
extern const struct drm_ioctl_desc radeon_ioctls_kms[];
extern int radeon_max_kms_ioctl;
int radeon_mmap(struct file *filp, struct vm_area_struct *vma);
@@ -144,11 +145,9 @@ void radeon_debugfs_cleanup(struct drm_minor *minor);
#if defined(CONFIG_VGA_SWITCHEROO)
void radeon_register_atpx_handler(void);
void radeon_unregister_atpx_handler(void);
-bool radeon_is_px(void);
#else
static inline void radeon_register_atpx_handler(void) {}
static inline void radeon_unregister_atpx_handler(void) {}
-static inline bool radeon_is_px(void) { return false; }
#endif
int radeon_no_wb;
@@ -186,7 +185,7 @@ module_param_named(dynclks, radeon_dynclks, int, 0444);
MODULE_PARM_DESC(r4xx_atom, "Enable ATOMBIOS modesetting for R4xx");
module_param_named(r4xx_atom, radeon_r4xx_atom, int, 0444);
-MODULE_PARM_DESC(vramlimit, "Restrict VRAM for testing");
+MODULE_PARM_DESC(vramlimit, "Restrict VRAM for testing, in megabytes");
module_param_named(vramlimit, radeon_vram_limit, int, 0600);
MODULE_PARM_DESC(agpmode, "AGP Mode (-1 == PCI)");
@@ -405,12 +404,7 @@ static int radeon_pmops_runtime_suspend(struct device *dev)
struct drm_device *drm_dev = pci_get_drvdata(pdev);
int ret;
- if (radeon_runtime_pm == 0) {
- pm_runtime_forbid(dev);
- return -EBUSY;
- }
-
- if (radeon_runtime_pm == -1 && !radeon_is_px()) {
+ if (!radeon_is_px(drm_dev)) {
pm_runtime_forbid(dev);
return -EBUSY;
}
@@ -434,10 +428,7 @@ static int radeon_pmops_runtime_resume(struct device *dev)
struct drm_device *drm_dev = pci_get_drvdata(pdev);
int ret;
- if (radeon_runtime_pm == 0)
- return -EINVAL;
-
- if (radeon_runtime_pm == -1 && !radeon_is_px())
+ if (!radeon_is_px(drm_dev))
return -EINVAL;
drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
@@ -462,14 +453,7 @@ static int radeon_pmops_runtime_idle(struct device *dev)
struct drm_device *drm_dev = pci_get_drvdata(pdev);
struct drm_crtc *crtc;
- if (radeon_runtime_pm == 0) {
- pm_runtime_forbid(dev);
- return -EBUSY;
- }
-
- /* are we PX enabled? */
- if (radeon_runtime_pm == -1 && !radeon_is_px()) {
- DRM_DEBUG_DRIVER("failing to power off - not px\n");
+ if (!radeon_is_px(drm_dev)) {
pm_runtime_forbid(dev);
return -EBUSY;
}
diff --git a/drivers/gpu/drm/radeon/radeon_family.h b/drivers/gpu/drm/radeon/radeon_family.h
index 614ad549297f..4b7b87f71a63 100644
--- a/drivers/gpu/drm/radeon/radeon_family.h
+++ b/drivers/gpu/drm/radeon/radeon_family.h
@@ -97,6 +97,7 @@ enum radeon_family {
CHIP_KAVERI,
CHIP_KABINI,
CHIP_HAWAII,
+ CHIP_MULLINS,
CHIP_LAST,
};
@@ -115,6 +116,7 @@ enum radeon_chip_flags {
RADEON_NEW_MEMMAP = 0x00400000UL,
RADEON_IS_PCI = 0x00800000UL,
RADEON_IS_IGPGART = 0x01000000UL,
+ RADEON_IS_PX = 0x02000000UL,
};
#endif
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
index e24ca6ab96de..7b944142a9fd 100644
--- a/drivers/gpu/drm/radeon/radeon_i2c.c
+++ b/drivers/gpu/drm/radeon/radeon_i2c.c
@@ -64,8 +64,7 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool use_aux)
radeon_router_select_ddc_port(radeon_connector);
if (use_aux) {
- struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;
- ret = i2c_transfer(&dig->dp_i2c_bus->adapter, msgs, 2);
+ ret = i2c_transfer(&radeon_connector->ddc_bus->aux.ddc, msgs, 2);
} else {
ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);
}
@@ -950,16 +949,16 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
/* set the radeon bit adapter */
snprintf(i2c->adapter.name, sizeof(i2c->adapter.name),
"Radeon i2c bit bus %s", name);
- i2c->adapter.algo_data = &i2c->algo.bit;
- i2c->algo.bit.pre_xfer = pre_xfer;
- i2c->algo.bit.post_xfer = post_xfer;
- i2c->algo.bit.setsda = set_data;
- i2c->algo.bit.setscl = set_clock;
- i2c->algo.bit.getsda = get_data;
- i2c->algo.bit.getscl = get_clock;
- i2c->algo.bit.udelay = 10;
- i2c->algo.bit.timeout = usecs_to_jiffies(2200); /* from VESA */
- i2c->algo.bit.data = i2c;
+ i2c->adapter.algo_data = &i2c->bit;
+ i2c->bit.pre_xfer = pre_xfer;
+ i2c->bit.post_xfer = post_xfer;
+ i2c->bit.setsda = set_data;
+ i2c->bit.setscl = set_clock;
+ i2c->bit.getsda = get_data;
+ i2c->bit.getscl = get_clock;
+ i2c->bit.udelay = 10;
+ i2c->bit.timeout = usecs_to_jiffies(2200); /* from VESA */
+ i2c->bit.data = i2c;
ret = i2c_bit_add_bus(&i2c->adapter);
if (ret) {
DRM_ERROR("Failed to register bit i2c %s\n", name);
@@ -974,46 +973,13 @@ out_free:
}
-struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev,
- struct radeon_i2c_bus_rec *rec,
- const char *name)
-{
- struct radeon_i2c_chan *i2c;
- int ret;
-
- i2c = kzalloc(sizeof(struct radeon_i2c_chan), GFP_KERNEL);
- if (i2c == NULL)
- return NULL;
-
- i2c->rec = *rec;
- i2c->adapter.owner = THIS_MODULE;
- i2c->adapter.class = I2C_CLASS_DDC;
- i2c->adapter.dev.parent = &dev->pdev->dev;
- i2c->dev = dev;
- snprintf(i2c->adapter.name, sizeof(i2c->adapter.name),
- "Radeon aux bus %s", name);
- i2c_set_adapdata(&i2c->adapter, i2c);
- i2c->adapter.algo_data = &i2c->algo.dp;
- i2c->algo.dp.aux_ch = radeon_dp_i2c_aux_ch;
- i2c->algo.dp.address = 0;
- ret = i2c_dp_aux_add_bus(&i2c->adapter);
- if (ret) {
- DRM_INFO("Failed to register i2c %s\n", name);
- goto out_free;
- }
-
- return i2c;
-out_free:
- kfree(i2c);
- return NULL;
-
-}
-
void radeon_i2c_destroy(struct radeon_i2c_chan *i2c)
{
if (!i2c)
return;
i2c_del_adapter(&i2c->adapter);
+ if (i2c->has_aux)
+ drm_dp_aux_unregister_i2c_bus(&i2c->aux);
kfree(i2c);
}
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index 3e49342a20e6..eaaedba04675 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -35,9 +35,9 @@
#include <linux/pm_runtime.h>
#if defined(CONFIG_VGA_SWITCHEROO)
-bool radeon_is_px(void);
+bool radeon_has_atpx(void);
#else
-static inline bool radeon_is_px(void) { return false; }
+static inline bool radeon_has_atpx(void) { return false; }
#endif
/**
@@ -107,6 +107,11 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
flags |= RADEON_IS_PCI;
}
+ if ((radeon_runtime_pm != 0) &&
+ radeon_has_atpx() &&
+ ((flags & RADEON_IS_IGP) == 0))
+ flags |= RADEON_IS_PX;
+
/* radeon_device_init should report only fatal error
* like memory allocation failure or iomapping failure,
* or memory manager initialization failure, it must
@@ -137,8 +142,7 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
"Error during ACPI methods call\n");
}
- if ((radeon_runtime_pm == 1) ||
- ((radeon_runtime_pm == -1) && radeon_is_px())) {
+ if (radeon_is_px(dev)) {
pm_runtime_use_autosuspend(dev->dev);
pm_runtime_set_autosuspend_delay(dev->dev, 5000);
pm_runtime_set_active(dev->dev);
@@ -568,28 +572,34 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
}
r = radeon_vm_init(rdev, &fpriv->vm);
- if (r)
- return r;
-
- r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false);
- if (r)
- 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);
-
- radeon_bo_unreserve(rdev->ring_tmp_bo.bo);
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);
+
+ 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;
}
@@ -617,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);
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 832d9fa1a4c4..6ddf31a2d34e 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -187,12 +187,10 @@ struct radeon_pll {
struct radeon_i2c_chan {
struct i2c_adapter adapter;
struct drm_device *dev;
- union {
- struct i2c_algo_bit_data bit;
- struct i2c_algo_dp_aux_data dp;
- } algo;
+ struct i2c_algo_bit_data bit;
struct radeon_i2c_bus_rec rec;
struct drm_dp_aux aux;
+ bool has_aux;
};
/* mostly for macs, but really any system without connector tables */
@@ -440,7 +438,6 @@ struct radeon_encoder {
struct radeon_connector_atom_dig {
uint32_t igp_lane_info;
/* displayport */
- struct radeon_i2c_chan *dp_i2c_bus;
u8 dpcd[DP_RECEIVER_CAP_SIZE];
u8 dp_sink_type;
int dp_clock;
@@ -702,8 +699,6 @@ extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder,
uint8_t lane_set);
extern void radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder);
extern struct drm_encoder *radeon_get_external_encoder(struct drm_encoder *encoder);
-extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
- u8 write_byte, u8 *read_byte);
void radeon_atom_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le);
extern void radeon_i2c_init(struct radeon_device *rdev);
@@ -715,9 +710,6 @@ extern void radeon_i2c_add(struct radeon_device *rdev,
const char *name);
extern struct radeon_i2c_chan *radeon_i2c_lookup(struct radeon_device *rdev,
struct radeon_i2c_bus_rec *i2c_bus);
-extern struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev,
- struct radeon_i2c_bus_rec *rec,
- const char *name);
extern struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
struct radeon_i2c_bus_rec *rec,
const char *name);
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c
index 19bec0dbfa38..4faa4d6f9bb4 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -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;
}
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c
index ee738a524639..53d6e1bb48dc 100644
--- a/drivers/gpu/drm/radeon/radeon_pm.c
+++ b/drivers/gpu/drm/radeon/radeon_pm.c
@@ -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
@@ -603,7 +639,6 @@ static const struct attribute_group *hwmon_groups[] = {
static int radeon_hwmon_init(struct radeon_device *rdev)
{
int err = 0;
- struct device *hwmon_dev;
switch (rdev->pm.int_thermal_type) {
case THERMAL_TYPE_RV6XX:
@@ -616,11 +651,11 @@ static int radeon_hwmon_init(struct radeon_device *rdev)
case THERMAL_TYPE_KV:
if (rdev->asic->pm.get_temperature == NULL)
return err;
- hwmon_dev = hwmon_device_register_with_groups(rdev->dev,
- "radeon", rdev,
- hwmon_groups);
- if (IS_ERR(hwmon_dev)) {
- err = PTR_ERR(hwmon_dev);
+ rdev->pm.int_hwmon_dev = hwmon_device_register_with_groups(rdev->dev,
+ "radeon", rdev,
+ hwmon_groups);
+ if (IS_ERR(rdev->pm.int_hwmon_dev)) {
+ err = PTR_ERR(rdev->pm.int_hwmon_dev);
dev_err(rdev->dev,
"Unable to register hwmon device: %d\n", err);
}
@@ -632,6 +667,12 @@ static int radeon_hwmon_init(struct radeon_device *rdev)
return err;
}
+static void radeon_hwmon_fini(struct radeon_device *rdev)
+{
+ if (rdev->pm.int_hwmon_dev)
+ hwmon_device_unregister(rdev->pm.int_hwmon_dev);
+}
+
static void radeon_dpm_thermal_work_handler(struct work_struct *work)
{
struct radeon_device *rdev =
@@ -1257,6 +1298,7 @@ int radeon_pm_init(struct radeon_device *rdev)
case CHIP_RV670:
case CHIP_RS780:
case CHIP_RS880:
+ case CHIP_RV770:
case CHIP_BARTS:
case CHIP_TURKS:
case CHIP_CAICOS:
@@ -1273,7 +1315,6 @@ int radeon_pm_init(struct radeon_device *rdev)
else
rdev->pm.pm_method = PM_METHOD_PROFILE;
break;
- case CHIP_RV770:
case CHIP_RV730:
case CHIP_RV710:
case CHIP_RV740:
@@ -1295,6 +1336,7 @@ int radeon_pm_init(struct radeon_device *rdev)
case CHIP_KABINI:
case CHIP_KAVERI:
case CHIP_HAWAII:
+ case CHIP_MULLINS:
/* DPM requires the RLC, RV770+ dGPU requires SMC */
if (!rdev->rlc_fw)
rdev->pm.pm_method = PM_METHOD_PROFILE;
@@ -1353,6 +1395,8 @@ static void radeon_pm_fini_old(struct radeon_device *rdev)
device_remove_file(rdev->dev, &dev_attr_power_method);
}
+ radeon_hwmon_fini(rdev);
+
if (rdev->pm.power_state)
kfree(rdev->pm.power_state);
}
@@ -1372,6 +1416,8 @@ static void radeon_pm_fini_dpm(struct radeon_device *rdev)
}
radeon_dpm_fini(rdev);
+ radeon_hwmon_fini(rdev);
+
if (rdev->pm.power_state)
kfree(rdev->pm.power_state);
}
@@ -1397,12 +1443,14 @@ static void radeon_pm_compute_clocks_old(struct radeon_device *rdev)
rdev->pm.active_crtcs = 0;
rdev->pm.active_crtc_count = 0;
- list_for_each_entry(crtc,
- &ddev->mode_config.crtc_list, head) {
- radeon_crtc = to_radeon_crtc(crtc);
- if (radeon_crtc->enabled) {
- rdev->pm.active_crtcs |= (1 << radeon_crtc->crtc_id);
- rdev->pm.active_crtc_count++;
+ if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) {
+ list_for_each_entry(crtc,
+ &ddev->mode_config.crtc_list, head) {
+ radeon_crtc = to_radeon_crtc(crtc);
+ if (radeon_crtc->enabled) {
+ rdev->pm.active_crtcs |= (1 << radeon_crtc->crtc_id);
+ rdev->pm.active_crtc_count++;
+ }
}
}
@@ -1469,12 +1517,14 @@ static void radeon_pm_compute_clocks_dpm(struct radeon_device *rdev)
/* update active crtc counts */
rdev->pm.dpm.new_active_crtcs = 0;
rdev->pm.dpm.new_active_crtc_count = 0;
- list_for_each_entry(crtc,
- &ddev->mode_config.crtc_list, head) {
- radeon_crtc = to_radeon_crtc(crtc);
- if (crtc->enabled) {
- rdev->pm.dpm.new_active_crtcs |= (1 << radeon_crtc->crtc_id);
- rdev->pm.dpm.new_active_crtc_count++;
+ if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) {
+ list_for_each_entry(crtc,
+ &ddev->mode_config.crtc_list, head) {
+ radeon_crtc = to_radeon_crtc(crtc);
+ if (crtc->enabled) {
+ rdev->pm.dpm.new_active_crtcs |= (1 << radeon_crtc->crtc_id);
+ rdev->pm.dpm.new_active_crtc_count++;
+ }
}
}
@@ -1600,8 +1650,12 @@ static int radeon_debugfs_pm_info(struct seq_file *m, void *data)
struct drm_info_node *node = (struct drm_info_node *) m->private;
struct drm_device *dev = node->minor->dev;
struct radeon_device *rdev = dev->dev_private;
+ struct drm_device *ddev = rdev->ddev;
- if (rdev->pm.dpm_enabled) {
+ if ((rdev->flags & RADEON_IS_PX) &&
+ (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) {
+ seq_printf(m, "PX asic powered off\n");
+ } else if (rdev->pm.dpm_enabled) {
mutex_lock(&rdev->pm.mutex);
if (rdev->asic->dpm.debugfs_print_current_performance_level)
radeon_dpm_debugfs_print_current_performance_level(rdev, m);
diff --git a/drivers/gpu/drm/radeon/radeon_ucode.h b/drivers/gpu/drm/radeon/radeon_ucode.h
index a77cd274dfc3..4e7c3269b183 100644
--- a/drivers/gpu/drm/radeon/radeon_ucode.h
+++ b/drivers/gpu/drm/radeon/radeon_ucode.h
@@ -52,14 +52,20 @@
#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
#define CAYMAN_MC_UCODE_SIZE 6037
#define SI_MC_UCODE_SIZE 7769
+#define TAHITI_MC_UCODE_SIZE 7808
+#define PITCAIRN_MC_UCODE_SIZE 7775
+#define VERDE_MC_UCODE_SIZE 7875
#define OLAND_MC_UCODE_SIZE 7863
-#define CIK_MC_UCODE_SIZE 7866
+#define BONAIRE_MC_UCODE_SIZE 7866
+#define BONAIRE_MC2_UCODE_SIZE 7948
#define HAWAII_MC_UCODE_SIZE 7933
+#define HAWAII_MC2_UCODE_SIZE 8091
/* SDMA */
#define CIK_SDMA_UCODE_SIZE 1050
diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c
index 5748bdaeacce..1b65ae2433cd 100644
--- a/drivers/gpu/drm/radeon/radeon_uvd.c
+++ b/drivers/gpu/drm/radeon/radeon_uvd.c
@@ -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]);
diff --git a/drivers/gpu/drm/radeon/radeon_vce.c b/drivers/gpu/drm/radeon/radeon_vce.c
index 76e9904bc537..3971d968af6c 100644
--- a/drivers/gpu/drm/radeon/radeon_vce.c
+++ b/drivers/gpu/drm/radeon/radeon_vce.c
@@ -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,15 +465,60 @@ 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
*
* @p: parser context
@@ -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;
}
/**
@@ -613,7 +684,7 @@ void radeon_vce_fence_emit(struct radeon_device *rdev,
struct radeon_fence *fence)
{
struct radeon_ring *ring = &rdev->ring[fence->ring];
- uint32_t addr = rdev->fence_drv[fence->ring].gpu_addr;
+ uint64_t addr = rdev->fence_drv[fence->ring].gpu_addr;
radeon_ring_write(ring, VCE_CMD_FENCE);
radeon_ring_write(ring, addr);
diff --git a/drivers/gpu/drm/radeon/radeon_vm.c b/drivers/gpu/drm/radeon/radeon_vm.c
index 2aae6ce49d32..1f426696de36 100644
--- a/drivers/gpu/drm/radeon/radeon_vm.c
+++ b/drivers/gpu/drm/radeon/radeon_vm.c
@@ -130,10 +130,10 @@ struct radeon_cs_reloc *radeon_vm_get_bos(struct radeon_device *rdev,
struct list_head *head)
{
struct radeon_cs_reloc *list;
- unsigned i, idx, size;
+ unsigned i, idx;
- size = (radeon_vm_num_pdes(rdev) + 1) * sizeof(struct radeon_cs_reloc);
- list = kmalloc(size, GFP_KERNEL);
+ list = kmalloc_array(vm->max_pde_used + 1,
+ sizeof(struct radeon_cs_reloc), GFP_KERNEL);
if (!list)
return NULL;
@@ -595,7 +595,7 @@ int radeon_vm_update_page_directory(struct radeon_device *rdev,
ndw = 64;
/* assume the worst case */
- ndw += vm->max_pde_used * 12;
+ ndw += vm->max_pde_used * 16;
/* update too big for an IB */
if (ndw > 0xfffff)
diff --git a/drivers/gpu/drm/radeon/rv770_dma.c b/drivers/gpu/drm/radeon/rv770_dma.c
index aca8cbe8a335..bbf2e076ee45 100644
--- a/drivers/gpu/drm/radeon/rv770_dma.c
+++ b/drivers/gpu/drm/radeon/rv770_dma.c
@@ -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;
}
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index d589475fe9e6..22a63c98ba14 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -39,30 +39,35 @@ MODULE_FIRMWARE("radeon/TAHITI_pfp.bin");
MODULE_FIRMWARE("radeon/TAHITI_me.bin");
MODULE_FIRMWARE("radeon/TAHITI_ce.bin");
MODULE_FIRMWARE("radeon/TAHITI_mc.bin");
+MODULE_FIRMWARE("radeon/TAHITI_mc2.bin");
MODULE_FIRMWARE("radeon/TAHITI_rlc.bin");
MODULE_FIRMWARE("radeon/TAHITI_smc.bin");
MODULE_FIRMWARE("radeon/PITCAIRN_pfp.bin");
MODULE_FIRMWARE("radeon/PITCAIRN_me.bin");
MODULE_FIRMWARE("radeon/PITCAIRN_ce.bin");
MODULE_FIRMWARE("radeon/PITCAIRN_mc.bin");
+MODULE_FIRMWARE("radeon/PITCAIRN_mc2.bin");
MODULE_FIRMWARE("radeon/PITCAIRN_rlc.bin");
MODULE_FIRMWARE("radeon/PITCAIRN_smc.bin");
MODULE_FIRMWARE("radeon/VERDE_pfp.bin");
MODULE_FIRMWARE("radeon/VERDE_me.bin");
MODULE_FIRMWARE("radeon/VERDE_ce.bin");
MODULE_FIRMWARE("radeon/VERDE_mc.bin");
+MODULE_FIRMWARE("radeon/VERDE_mc2.bin");
MODULE_FIRMWARE("radeon/VERDE_rlc.bin");
MODULE_FIRMWARE("radeon/VERDE_smc.bin");
MODULE_FIRMWARE("radeon/OLAND_pfp.bin");
MODULE_FIRMWARE("radeon/OLAND_me.bin");
MODULE_FIRMWARE("radeon/OLAND_ce.bin");
MODULE_FIRMWARE("radeon/OLAND_mc.bin");
+MODULE_FIRMWARE("radeon/OLAND_mc2.bin");
MODULE_FIRMWARE("radeon/OLAND_rlc.bin");
MODULE_FIRMWARE("radeon/OLAND_smc.bin");
MODULE_FIRMWARE("radeon/HAINAN_pfp.bin");
MODULE_FIRMWARE("radeon/HAINAN_me.bin");
MODULE_FIRMWARE("radeon/HAINAN_ce.bin");
MODULE_FIRMWARE("radeon/HAINAN_mc.bin");
+MODULE_FIRMWARE("radeon/HAINAN_mc2.bin");
MODULE_FIRMWARE("radeon/HAINAN_rlc.bin");
MODULE_FIRMWARE("radeon/HAINAN_smc.bin");
@@ -1467,36 +1472,33 @@ int si_mc_load_microcode(struct radeon_device *rdev)
const __be32 *fw_data;
u32 running, blackout = 0;
u32 *io_mc_regs;
- int i, ucode_size, regs_size;
+ int i, regs_size, ucode_size;
if (!rdev->mc_fw)
return -EINVAL;
+ ucode_size = rdev->mc_fw->size / 4;
+
switch (rdev->family) {
case CHIP_TAHITI:
io_mc_regs = (u32 *)&tahiti_io_mc_regs;
- ucode_size = SI_MC_UCODE_SIZE;
regs_size = TAHITI_IO_MC_REGS_SIZE;
break;
case CHIP_PITCAIRN:
io_mc_regs = (u32 *)&pitcairn_io_mc_regs;
- ucode_size = SI_MC_UCODE_SIZE;
regs_size = TAHITI_IO_MC_REGS_SIZE;
break;
case CHIP_VERDE:
default:
io_mc_regs = (u32 *)&verde_io_mc_regs;
- ucode_size = SI_MC_UCODE_SIZE;
regs_size = TAHITI_IO_MC_REGS_SIZE;
break;
case CHIP_OLAND:
io_mc_regs = (u32 *)&oland_io_mc_regs;
- ucode_size = OLAND_MC_UCODE_SIZE;
regs_size = TAHITI_IO_MC_REGS_SIZE;
break;
case CHIP_HAINAN:
io_mc_regs = (u32 *)&hainan_io_mc_regs;
- ucode_size = OLAND_MC_UCODE_SIZE;
regs_size = TAHITI_IO_MC_REGS_SIZE;
break;
}
@@ -1552,7 +1554,7 @@ static int si_init_microcode(struct radeon_device *rdev)
const char *chip_name;
const char *rlc_chip_name;
size_t pfp_req_size, me_req_size, ce_req_size, rlc_req_size, mc_req_size;
- size_t smc_req_size;
+ size_t smc_req_size, mc2_req_size;
char fw_name[30];
int err;
@@ -1567,6 +1569,7 @@ static int si_init_microcode(struct radeon_device *rdev)
ce_req_size = SI_CE_UCODE_SIZE * 4;
rlc_req_size = SI_RLC_UCODE_SIZE * 4;
mc_req_size = SI_MC_UCODE_SIZE * 4;
+ mc2_req_size = TAHITI_MC_UCODE_SIZE * 4;
smc_req_size = ALIGN(TAHITI_SMC_UCODE_SIZE, 4);
break;
case CHIP_PITCAIRN:
@@ -1577,6 +1580,7 @@ static int si_init_microcode(struct radeon_device *rdev)
ce_req_size = SI_CE_UCODE_SIZE * 4;
rlc_req_size = SI_RLC_UCODE_SIZE * 4;
mc_req_size = SI_MC_UCODE_SIZE * 4;
+ mc2_req_size = PITCAIRN_MC_UCODE_SIZE * 4;
smc_req_size = ALIGN(PITCAIRN_SMC_UCODE_SIZE, 4);
break;
case CHIP_VERDE:
@@ -1587,6 +1591,7 @@ static int si_init_microcode(struct radeon_device *rdev)
ce_req_size = SI_CE_UCODE_SIZE * 4;
rlc_req_size = SI_RLC_UCODE_SIZE * 4;
mc_req_size = SI_MC_UCODE_SIZE * 4;
+ mc2_req_size = VERDE_MC_UCODE_SIZE * 4;
smc_req_size = ALIGN(VERDE_SMC_UCODE_SIZE, 4);
break;
case CHIP_OLAND:
@@ -1596,7 +1601,7 @@ static int si_init_microcode(struct radeon_device *rdev)
me_req_size = SI_PM4_UCODE_SIZE * 4;
ce_req_size = SI_CE_UCODE_SIZE * 4;
rlc_req_size = SI_RLC_UCODE_SIZE * 4;
- mc_req_size = OLAND_MC_UCODE_SIZE * 4;
+ mc_req_size = mc2_req_size = OLAND_MC_UCODE_SIZE * 4;
smc_req_size = ALIGN(OLAND_SMC_UCODE_SIZE, 4);
break;
case CHIP_HAINAN:
@@ -1606,7 +1611,7 @@ static int si_init_microcode(struct radeon_device *rdev)
me_req_size = SI_PM4_UCODE_SIZE * 4;
ce_req_size = SI_CE_UCODE_SIZE * 4;
rlc_req_size = SI_RLC_UCODE_SIZE * 4;
- mc_req_size = OLAND_MC_UCODE_SIZE * 4;
+ mc_req_size = mc2_req_size = OLAND_MC_UCODE_SIZE * 4;
smc_req_size = ALIGN(HAINAN_SMC_UCODE_SIZE, 4);
break;
default: BUG();
@@ -1659,16 +1664,22 @@ static int si_init_microcode(struct radeon_device *rdev)
err = -EINVAL;
}
- snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name);
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc2.bin", chip_name);
err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev);
- if (err)
- goto out;
- if (rdev->mc_fw->size != mc_req_size) {
+ if (err) {
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name);
+ err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev);
+ if (err)
+ goto out;
+ }
+ if ((rdev->mc_fw->size != mc_req_size) &&
+ (rdev->mc_fw->size != mc2_req_size)) {
printk(KERN_ERR
"si_mc: Bogus length %zu in firmware \"%s\"\n",
rdev->mc_fw->size, fw_name);
err = -EINVAL;
}
+ DRM_INFO("%s: %zu bytes\n", fw_name, rdev->mc_fw->size);
snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", chip_name);
err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev);
@@ -5769,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;
@@ -5908,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)) {
@@ -6281,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:
diff --git a/drivers/gpu/drm/radeon/si_dma.c b/drivers/gpu/drm/radeon/si_dma.c
index cf0fdad8c278..de0ca070122f 100644
--- a/drivers/gpu/drm/radeon/si_dma.c
+++ b/drivers/gpu/drm/radeon/si_dma.c
@@ -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;
}
diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h
index 683532f84931..7321283602ce 100644
--- a/drivers/gpu/drm/radeon/sid.h
+++ b/drivers/gpu/drm/radeon/sid.h
@@ -107,8 +107,8 @@
#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)
diff --git a/drivers/gpu/drm/radeon/uvd_v1_0.c b/drivers/gpu/drm/radeon/uvd_v1_0.c
index 0a243f0e5d68..be42c8125203 100644
--- a/drivers/gpu/drm/radeon/uvd_v1_0.c
+++ b/drivers/gpu/drm/radeon/uvd_v1_0.c
@@ -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;
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 36c717af6cf9..edb871d7d395 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -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;
diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c
index d536ed381fbd..005c19bd92df 100644
--- a/drivers/gpu/drm/tegra/dpaux.c
+++ b/drivers/gpu/drm/tegra/dpaux.c
@@ -99,55 +99,73 @@ static void tegra_dpaux_read_fifo(struct tegra_dpaux *dpaux, u8 *buffer,
static ssize_t tegra_dpaux_transfer(struct drm_dp_aux *aux,
struct drm_dp_aux_msg *msg)
{
- unsigned long value = DPAUX_DP_AUXCTL_TRANSACTREQ;
unsigned long timeout = msecs_to_jiffies(250);
struct tegra_dpaux *dpaux = to_dpaux(aux);
unsigned long status;
ssize_t ret = 0;
+ u32 value;
- if (msg->size < 1 || msg->size > 16)
+ /* Tegra has 4x4 byte DP AUX transmit and receive FIFOs. */
+ if (msg->size > 16)
return -EINVAL;
- tegra_dpaux_writel(dpaux, msg->address, DPAUX_DP_AUXADDR);
+ /*
+ * Allow zero-sized messages only for I2C, in which case they specify
+ * address-only transactions.
+ */
+ if (msg->size < 1) {
+ switch (msg->request & ~DP_AUX_I2C_MOT) {
+ case DP_AUX_I2C_WRITE:
+ case DP_AUX_I2C_READ:
+ value = DPAUX_DP_AUXCTL_CMD_ADDRESS_ONLY;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ } else {
+ /* For non-zero-sized messages, set the CMDLEN field. */
+ value = DPAUX_DP_AUXCTL_CMDLEN(msg->size - 1);
+ }
switch (msg->request & ~DP_AUX_I2C_MOT) {
case DP_AUX_I2C_WRITE:
if (msg->request & DP_AUX_I2C_MOT)
- value = DPAUX_DP_AUXCTL_CMD_MOT_WR;
+ value |= DPAUX_DP_AUXCTL_CMD_MOT_WR;
else
- value = DPAUX_DP_AUXCTL_CMD_I2C_WR;
+ value |= DPAUX_DP_AUXCTL_CMD_I2C_WR;
break;
case DP_AUX_I2C_READ:
if (msg->request & DP_AUX_I2C_MOT)
- value = DPAUX_DP_AUXCTL_CMD_MOT_RD;
+ value |= DPAUX_DP_AUXCTL_CMD_MOT_RD;
else
- value = DPAUX_DP_AUXCTL_CMD_I2C_RD;
+ value |= DPAUX_DP_AUXCTL_CMD_I2C_RD;
break;
case DP_AUX_I2C_STATUS:
if (msg->request & DP_AUX_I2C_MOT)
- value = DPAUX_DP_AUXCTL_CMD_MOT_RQ;
+ value |= DPAUX_DP_AUXCTL_CMD_MOT_RQ;
else
- value = DPAUX_DP_AUXCTL_CMD_I2C_RQ;
+ value |= DPAUX_DP_AUXCTL_CMD_I2C_RQ;
break;
case DP_AUX_NATIVE_WRITE:
- value = DPAUX_DP_AUXCTL_CMD_AUX_WR;
+ value |= DPAUX_DP_AUXCTL_CMD_AUX_WR;
break;
case DP_AUX_NATIVE_READ:
- value = DPAUX_DP_AUXCTL_CMD_AUX_RD;
+ value |= DPAUX_DP_AUXCTL_CMD_AUX_RD;
break;
default:
return -EINVAL;
}
- value |= DPAUX_DP_AUXCTL_CMDLEN(msg->size - 1);
+ tegra_dpaux_writel(dpaux, msg->address, DPAUX_DP_AUXADDR);
tegra_dpaux_writel(dpaux, value, DPAUX_DP_AUXCTL);
if ((msg->request & DP_AUX_I2C_READ) == 0) {
@@ -198,7 +216,7 @@ static ssize_t tegra_dpaux_transfer(struct drm_dp_aux *aux,
break;
}
- if (msg->reply == DP_AUX_NATIVE_REPLY_ACK) {
+ if ((msg->size > 0) && (msg->reply == DP_AUX_NATIVE_REPLY_ACK)) {
if (msg->request & DP_AUX_I2C_READ) {
size_t count = value & DPAUX_DP_AUXSTAT_REPLY_MASK;
diff --git a/drivers/gpu/drm/tegra/dpaux.h b/drivers/gpu/drm/tegra/dpaux.h
index 4f5bf10fdff9..806e245ca787 100644
--- a/drivers/gpu/drm/tegra/dpaux.h
+++ b/drivers/gpu/drm/tegra/dpaux.h
@@ -32,6 +32,7 @@
#define DPAUX_DP_AUXCTL_CMD_I2C_RQ (2 << 12)
#define DPAUX_DP_AUXCTL_CMD_I2C_RD (1 << 12)
#define DPAUX_DP_AUXCTL_CMD_I2C_WR (0 << 12)
+#define DPAUX_DP_AUXCTL_CMD_ADDRESS_ONLY (1 << 8)
#define DPAUX_DP_AUXCTL_CMDLEN(x) ((x) & 0xff)
#define DPAUX_DP_AUXSTAT 0x31
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index 931490b9cfed..87df0b3674fd 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -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);
diff --git a/drivers/gpu/host1x/hw/intr_hw.c b/drivers/gpu/host1x/hw/intr_hw.c
index db9017adfe2b..498b37e39058 100644
--- a/drivers/gpu/host1x/hw/intr_hw.c
+++ b/drivers/gpu/host1x/hw/intr_hw.c
@@ -47,7 +47,7 @@ static irqreturn_t syncpt_thresh_isr(int irq, void *dev_id)
unsigned long reg;
int i, id;
- for (i = 0; i <= BIT_WORD(host->info->nb_pts); i++) {
+ for (i = 0; i < DIV_ROUND_UP(host->info->nb_pts, 32); i++) {
reg = host1x_sync_readl(host,
HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(i));
for_each_set_bit(id, &reg, BITS_PER_LONG) {
@@ -64,7 +64,7 @@ static void _host1x_intr_disable_all_syncpt_intrs(struct host1x *host)
{
u32 i;
- for (i = 0; i <= BIT_WORD(host->info->nb_pts); ++i) {
+ for (i = 0; i < DIV_ROUND_UP(host->info->nb_pts, 32); ++i) {
host1x_sync_writel(host, 0xffffffffu,
HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(i));
host1x_sync_writel(host, 0xffffffffu,
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 9e8064205bc7..da52279de939 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -718,6 +718,9 @@ static int hid_scan_main(struct hid_parser *parser, struct hid_item *item)
case HID_MAIN_ITEM_TAG_END_COLLECTION:
break;
case HID_MAIN_ITEM_TAG_INPUT:
+ /* ignore constant inputs, they will be ignored by hid-input */
+ if (data & HID_MAIN_ITEM_CONSTANT)
+ break;
for (i = 0; i < parser->local.usage_index; i++)
hid_scan_input_usage(parser, parser->local.usage[i]);
break;
@@ -1250,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);
}
/*
@@ -1263,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);
}
@@ -1821,8 +1825,6 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) },
- { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2) },
- { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_OFFICE_KB) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index bd221263c739..34bb2205d2ea 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -301,6 +301,9 @@
#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
@@ -455,7 +458,8 @@
#define USB_VENDOR_ID_INTEL_0 0x8086
#define USB_VENDOR_ID_INTEL_1 0x8087
-#define USB_DEVICE_ID_INTEL_HID_SENSOR 0x09fa
+#define USB_DEVICE_ID_INTEL_HID_SENSOR_0 0x09fa
+#define USB_DEVICE_ID_INTEL_HID_SENSOR_1 0x0a04
#define USB_VENDOR_ID_STM_0 0x0483
#define USB_DEVICE_ID_STM_HID_SENSOR 0x91d1
@@ -629,8 +633,6 @@
#define USB_DEVICE_ID_MS_PRESENTER_8K_USB 0x0713
#define USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K 0x0730
#define USB_DEVICE_ID_MS_COMFORT_MOUSE_4500 0x076c
-#define USB_DEVICE_ID_MS_TOUCH_COVER_2 0x07a7
-#define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9
#define USB_VENDOR_ID_MOJO 0x8282
#define USB_DEVICE_ID_RETRO_ADAPTER 0x3201
@@ -835,6 +837,10 @@
#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
diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c
index 6fd58175a291..8ba17a946f2a 100644
--- a/drivers/hid/hid-microsoft.c
+++ b/drivers/hid/hid-microsoft.c
@@ -274,10 +274,6 @@ static const struct hid_device_id ms_devices[] = {
.driver_data = MS_NOGET },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500),
.driver_data = MS_DUPLICATE_USAGES },
- { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2),
- .driver_data = 0 },
- { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2),
- .driver_data = 0 },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT),
.driver_data = MS_PRESENTER },
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 35278e43c7a4..51e25b9407f2 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -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,
diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c
index 5182031f7b52..be14b5690e94 100644
--- a/drivers/hid/hid-sensor-hub.c
+++ b/drivers/hid/hid-sensor-hub.c
@@ -697,14 +697,20 @@ static void sensor_hub_remove(struct hid_device *hdev)
static const struct hid_device_id sensor_hub_devices[] = {
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_INTEL_0,
- USB_DEVICE_ID_INTEL_HID_SENSOR),
+ USB_DEVICE_ID_INTEL_HID_SENSOR_0),
.driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_INTEL_1,
- USB_DEVICE_ID_INTEL_HID_SENSOR),
+ USB_DEVICE_ID_INTEL_HID_SENSOR_0),
+ .driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
+ { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_INTEL_1,
+ USB_DEVICE_ID_INTEL_HID_SENSOR_1),
.driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
{ 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) },
{ }
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 69204afea7a4..908de2789219 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -1721,8 +1721,6 @@ static void sony_remove(struct hid_device *hdev)
if (sc->quirks & SONY_LED_SUPPORT)
sony_leds_remove(hdev);
- if (sc->worker_initialized)
- cancel_work_sync(&sc->state_worker);
if (sc->quirks & SONY_BATTERY_SUPPORT) {
hid_hw_close(hdev);
sony_battery_remove(sc);
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index dbd83878ff99..8e4ddb369883 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -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 }
};
diff --git a/drivers/hsi/Kconfig b/drivers/hsi/Kconfig
index d94e38dd80c7..2c76de438eb1 100644
--- a/drivers/hsi/Kconfig
+++ b/drivers/hsi/Kconfig
@@ -14,6 +14,7 @@ config HSI_BOARDINFO
bool
default y
+source "drivers/hsi/controllers/Kconfig"
source "drivers/hsi/clients/Kconfig"
endif # HSI
diff --git a/drivers/hsi/Makefile b/drivers/hsi/Makefile
index 9d5d33f90de2..360371e134f1 100644
--- a/drivers/hsi/Makefile
+++ b/drivers/hsi/Makefile
@@ -3,4 +3,5 @@
#
obj-$(CONFIG_HSI_BOARDINFO) += hsi_boardinfo.o
obj-$(CONFIG_HSI) += hsi.o
+obj-y += controllers/
obj-y += clients/
diff --git a/drivers/hsi/clients/Kconfig b/drivers/hsi/clients/Kconfig
index 3bacd275f479..71b9f9ab86e4 100644
--- a/drivers/hsi/clients/Kconfig
+++ b/drivers/hsi/clients/Kconfig
@@ -4,6 +4,23 @@
comment "HSI clients"
+config NOKIA_MODEM
+ tristate "Nokia Modem"
+ depends on HSI && SSI_PROTOCOL
+ help
+ Say Y here if you want to add support for the modem on Nokia
+ N900 (Nokia RX-51) hardware.
+
+ If unsure, say N.
+
+config SSI_PROTOCOL
+ tristate "SSI protocol"
+ depends on HSI && PHONET && (OMAP_SSI=y || OMAP_SSI=m)
+ help
+ If you say Y here, you will enable the SSI protocol aka McSAAB.
+
+ If unsure, say N.
+
config HSI_CHAR
tristate "HSI/SSI character driver"
depends on HSI
diff --git a/drivers/hsi/clients/Makefile b/drivers/hsi/clients/Makefile
index 327c0e27c8b0..4d5bc0e0b27b 100644
--- a/drivers/hsi/clients/Makefile
+++ b/drivers/hsi/clients/Makefile
@@ -2,4 +2,6 @@
# Makefile for HSI clients
#
-obj-$(CONFIG_HSI_CHAR) += hsi_char.o
+obj-$(CONFIG_NOKIA_MODEM) += nokia-modem.o
+obj-$(CONFIG_SSI_PROTOCOL) += ssi_protocol.o
+obj-$(CONFIG_HSI_CHAR) += hsi_char.o
diff --git a/drivers/hsi/clients/hsi_char.c b/drivers/hsi/clients/hsi_char.c
index e61e5f991aa5..57f70c28fa38 100644
--- a/drivers/hsi/clients/hsi_char.c
+++ b/drivers/hsi/clients/hsi_char.c
@@ -367,7 +367,7 @@ static int hsc_rx_set(struct hsi_client *cl, struct hsc_rx_config *rxc)
return -EINVAL;
tmp = cl->rx_cfg;
cl->rx_cfg.mode = rxc->mode;
- cl->rx_cfg.channels = rxc->channels;
+ cl->rx_cfg.num_hw_channels = rxc->channels;
cl->rx_cfg.flow = rxc->flow;
ret = hsi_setup(cl);
if (ret < 0) {
@@ -383,7 +383,7 @@ static int hsc_rx_set(struct hsi_client *cl, struct hsc_rx_config *rxc)
static inline void hsc_rx_get(struct hsi_client *cl, struct hsc_rx_config *rxc)
{
rxc->mode = cl->rx_cfg.mode;
- rxc->channels = cl->rx_cfg.channels;
+ rxc->channels = cl->rx_cfg.num_hw_channels;
rxc->flow = cl->rx_cfg.flow;
}
@@ -402,7 +402,7 @@ static int hsc_tx_set(struct hsi_client *cl, struct hsc_tx_config *txc)
return -EINVAL;
tmp = cl->tx_cfg;
cl->tx_cfg.mode = txc->mode;
- cl->tx_cfg.channels = txc->channels;
+ cl->tx_cfg.num_hw_channels = txc->channels;
cl->tx_cfg.speed = txc->speed;
cl->tx_cfg.arb_mode = txc->arb_mode;
ret = hsi_setup(cl);
@@ -417,7 +417,7 @@ static int hsc_tx_set(struct hsi_client *cl, struct hsc_tx_config *txc)
static inline void hsc_tx_get(struct hsi_client *cl, struct hsc_tx_config *txc)
{
txc->mode = cl->tx_cfg.mode;
- txc->channels = cl->tx_cfg.channels;
+ txc->channels = cl->tx_cfg.num_hw_channels;
txc->speed = cl->tx_cfg.speed;
txc->arb_mode = cl->tx_cfg.arb_mode;
}
@@ -435,7 +435,7 @@ static ssize_t hsc_read(struct file *file, char __user *buf, size_t len,
return -EINVAL;
if (len > max_data_size)
len = max_data_size;
- if (channel->ch >= channel->cl->rx_cfg.channels)
+ if (channel->ch >= channel->cl->rx_cfg.num_hw_channels)
return -ECHRNG;
if (test_and_set_bit(HSC_CH_READ, &channel->flags))
return -EBUSY;
@@ -492,7 +492,7 @@ static ssize_t hsc_write(struct file *file, const char __user *buf, size_t len,
return -EINVAL;
if (len > max_data_size)
len = max_data_size;
- if (channel->ch >= channel->cl->tx_cfg.channels)
+ if (channel->ch >= channel->cl->tx_cfg.num_hw_channels)
return -ECHRNG;
if (test_and_set_bit(HSC_CH_WRITE, &channel->flags))
return -EBUSY;
@@ -705,7 +705,7 @@ static int hsc_probe(struct device *dev)
if (!hsc_major) {
ret = alloc_chrdev_region(&hsc_dev, hsc_baseminor,
HSC_DEVS, devname);
- if (ret > 0)
+ if (ret == 0)
hsc_major = MAJOR(hsc_dev);
} else {
hsc_dev = MKDEV(hsc_major, hsc_baseminor);
diff --git a/drivers/hsi/clients/nokia-modem.c b/drivers/hsi/clients/nokia-modem.c
new file mode 100644
index 000000000000..363b780dacea
--- /dev/null
+++ b/drivers/hsi/clients/nokia-modem.c
@@ -0,0 +1,285 @@
+/*
+ * nokia-modem.c
+ *
+ * HSI client driver for Nokia N900 modem.
+ *
+ * Copyright (C) 2014 Sebastian Reichel <sre@kernel.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/gpio/consumer.h>
+#include <linux/hsi/hsi.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_gpio.h>
+#include <linux/hsi/ssi_protocol.h>
+
+static unsigned int pm;
+module_param(pm, int, 0400);
+MODULE_PARM_DESC(pm,
+ "Enable power management (0=disabled, 1=userland based [default])");
+
+struct nokia_modem_gpio {
+ struct gpio_desc *gpio;
+ const char *name;
+};
+
+struct nokia_modem_device {
+ struct tasklet_struct nokia_modem_rst_ind_tasklet;
+ int nokia_modem_rst_ind_irq;
+ struct device *device;
+ struct nokia_modem_gpio *gpios;
+ int gpio_amount;
+ struct hsi_client *ssi_protocol;
+};
+
+static void do_nokia_modem_rst_ind_tasklet(unsigned long data)
+{
+ struct nokia_modem_device *modem = (struct nokia_modem_device *)data;
+
+ if (!modem)
+ return;
+
+ dev_info(modem->device, "CMT rst line change detected\n");
+
+ if (modem->ssi_protocol)
+ ssip_reset_event(modem->ssi_protocol);
+}
+
+static irqreturn_t nokia_modem_rst_ind_isr(int irq, void *data)
+{
+ struct nokia_modem_device *modem = (struct nokia_modem_device *)data;
+
+ tasklet_schedule(&modem->nokia_modem_rst_ind_tasklet);
+
+ return IRQ_HANDLED;
+}
+
+static void nokia_modem_gpio_unexport(struct device *dev)
+{
+ struct nokia_modem_device *modem = dev_get_drvdata(dev);
+ int i;
+
+ for (i = 0; i < modem->gpio_amount; i++) {
+ sysfs_remove_link(&dev->kobj, modem->gpios[i].name);
+ gpiod_unexport(modem->gpios[i].gpio);
+ }
+}
+
+static int nokia_modem_gpio_probe(struct device *dev)
+{
+ struct device_node *np = dev->of_node;
+ struct nokia_modem_device *modem = dev_get_drvdata(dev);
+ int gpio_count, gpio_name_count, i, err;
+
+ gpio_count = of_gpio_count(np);
+
+ if (gpio_count < 0) {
+ dev_err(dev, "missing gpios: %d\n", gpio_count);
+ return gpio_count;
+ }
+
+ gpio_name_count = of_property_count_strings(np, "gpio-names");
+
+ if (gpio_count != gpio_name_count) {
+ dev_err(dev, "number of gpios does not equal number of gpio names\n");
+ return -EINVAL;
+ }
+
+ modem->gpios = devm_kzalloc(dev, gpio_count *
+ sizeof(struct nokia_modem_gpio), GFP_KERNEL);
+ if (!modem->gpios) {
+ dev_err(dev, "Could not allocate memory for gpios\n");
+ return -ENOMEM;
+ }
+
+ modem->gpio_amount = gpio_count;
+
+ for (i = 0; i < gpio_count; i++) {
+ modem->gpios[i].gpio = devm_gpiod_get_index(dev, NULL, i);
+ if (IS_ERR(modem->gpios[i].gpio)) {
+ dev_err(dev, "Could not get gpio %d\n", i);
+ return PTR_ERR(modem->gpios[i].gpio);
+ }
+
+ err = of_property_read_string_index(np, "gpio-names", i,
+ &(modem->gpios[i].name));
+ if (err) {
+ dev_err(dev, "Could not get gpio name %d\n", i);
+ return err;
+ }
+
+ err = gpiod_direction_output(modem->gpios[i].gpio, 0);
+ if (err)
+ return err;
+
+ err = gpiod_export(modem->gpios[i].gpio, 0);
+ if (err)
+ return err;
+
+ err = gpiod_export_link(dev, modem->gpios[i].name,
+ modem->gpios[i].gpio);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static int nokia_modem_probe(struct device *dev)
+{
+ struct device_node *np;
+ struct nokia_modem_device *modem;
+ struct hsi_client *cl = to_hsi_client(dev);
+ struct hsi_port *port = hsi_get_port(cl);
+ int irq, pflags, err;
+ struct hsi_board_info ssip;
+
+ np = dev->of_node;
+ if (!np) {
+ dev_err(dev, "device tree node not found\n");
+ return -ENXIO;
+ }
+
+ modem = devm_kzalloc(dev, sizeof(*modem), GFP_KERNEL);
+ if (!modem) {
+ dev_err(dev, "Could not allocate memory for nokia_modem_device\n");
+ return -ENOMEM;
+ }
+ dev_set_drvdata(dev, modem);
+
+ irq = irq_of_parse_and_map(np, 0);
+ if (irq < 0) {
+ dev_err(dev, "Invalid rst_ind interrupt (%d)\n", irq);
+ return irq;
+ }
+ modem->nokia_modem_rst_ind_irq = irq;
+ pflags = irq_get_trigger_type(irq);
+
+ tasklet_init(&modem->nokia_modem_rst_ind_tasklet,
+ do_nokia_modem_rst_ind_tasklet, (unsigned long)modem);
+ err = devm_request_irq(dev, irq, nokia_modem_rst_ind_isr,
+ IRQF_DISABLED | pflags, "modem_rst_ind", modem);
+ if (err < 0) {
+ dev_err(dev, "Request rst_ind irq(%d) failed (flags %d)\n",
+ irq, pflags);
+ return err;
+ }
+ enable_irq_wake(irq);
+
+ if(pm) {
+ err = nokia_modem_gpio_probe(dev);
+ if (err < 0) {
+ dev_err(dev, "Could not probe GPIOs\n");
+ goto error1;
+ }
+ }
+
+ ssip.name = "ssi-protocol";
+ ssip.tx_cfg = cl->tx_cfg;
+ ssip.rx_cfg = cl->rx_cfg;
+ ssip.platform_data = NULL;
+ ssip.archdata = NULL;
+
+ modem->ssi_protocol = hsi_new_client(port, &ssip);
+ if (!modem->ssi_protocol) {
+ dev_err(dev, "Could not register ssi-protocol device\n");
+ goto error2;
+ }
+
+ err = device_attach(&modem->ssi_protocol->device);
+ if (err == 0) {
+ dev_err(dev, "Missing ssi-protocol driver\n");
+ err = -EPROBE_DEFER;
+ goto error3;
+ } else if (err < 0) {
+ dev_err(dev, "Could not load ssi-protocol driver (%d)\n", err);
+ goto error3;
+ }
+
+ /* TODO: register cmt-speech hsi client */
+
+ dev_info(dev, "Registered Nokia HSI modem\n");
+
+ return 0;
+
+error3:
+ hsi_remove_client(&modem->ssi_protocol->device, NULL);
+error2:
+ nokia_modem_gpio_unexport(dev);
+error1:
+ disable_irq_wake(modem->nokia_modem_rst_ind_irq);
+ tasklet_kill(&modem->nokia_modem_rst_ind_tasklet);
+
+ return err;
+}
+
+static int nokia_modem_remove(struct device *dev)
+{
+ struct nokia_modem_device *modem = dev_get_drvdata(dev);
+
+ if (!modem)
+ return 0;
+
+ if (modem->ssi_protocol) {
+ hsi_remove_client(&modem->ssi_protocol->device, NULL);
+ modem->ssi_protocol = NULL;
+ }
+
+ nokia_modem_gpio_unexport(dev);
+ dev_set_drvdata(dev, NULL);
+ disable_irq_wake(modem->nokia_modem_rst_ind_irq);
+ tasklet_kill(&modem->nokia_modem_rst_ind_tasklet);
+
+ return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id nokia_modem_of_match[] = {
+ { .compatible = "nokia,n900-modem", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, nokia_modem_of_match);
+#endif
+
+static struct hsi_client_driver nokia_modem_driver = {
+ .driver = {
+ .name = "nokia-modem",
+ .owner = THIS_MODULE,
+ .probe = nokia_modem_probe,
+ .remove = nokia_modem_remove,
+ .of_match_table = of_match_ptr(nokia_modem_of_match),
+ },
+};
+
+static int __init nokia_modem_init(void)
+{
+ return hsi_register_client_driver(&nokia_modem_driver);
+}
+module_init(nokia_modem_init);
+
+static void __exit nokia_modem_exit(void)
+{
+ hsi_unregister_client_driver(&nokia_modem_driver);
+}
+module_exit(nokia_modem_exit);
+
+MODULE_ALIAS("hsi:nokia-modem");
+MODULE_AUTHOR("Sebastian Reichel <sre@kernel.org>");
+MODULE_DESCRIPTION("HSI driver module for Nokia N900 Modem");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hsi/clients/ssi_protocol.c b/drivers/hsi/clients/ssi_protocol.c
new file mode 100644
index 000000000000..ce4be3738d46
--- /dev/null
+++ b/drivers/hsi/clients/ssi_protocol.c
@@ -0,0 +1,1191 @@
+/*
+ * ssi_protocol.c
+ *
+ * Implementation of the SSI McSAAB improved protocol.
+ *
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ * Copyright (C) 2013 Sebastian Reichel <sre@kernel.org>
+ *
+ * Contact: Carlos Chinea <carlos.chinea@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/atomic.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/if_ether.h>
+#include <linux/if_arp.h>
+#include <linux/if_phonet.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/notifier.h>
+#include <linux/scatterlist.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include <linux/hsi/hsi.h>
+#include <linux/hsi/ssi_protocol.h>
+
+void ssi_waketest(struct hsi_client *cl, unsigned int enable);
+
+#define SSIP_TXQUEUE_LEN 100
+#define SSIP_MAX_MTU 65535
+#define SSIP_DEFAULT_MTU 4000
+#define PN_MEDIA_SOS 21
+#define SSIP_MIN_PN_HDR 6 /* FIXME: Revisit */
+#define SSIP_WDTOUT 2000 /* FIXME: has to be 500 msecs */
+#define SSIP_KATOUT 15 /* 15 msecs */
+#define SSIP_MAX_CMDS 5 /* Number of pre-allocated commands buffers */
+#define SSIP_BYTES_TO_FRAMES(x) ((((x) - 1) >> 2) + 1)
+#define SSIP_CMT_LOADER_SYNC 0x11223344
+/*
+ * SSI protocol command definitions
+ */
+#define SSIP_COMMAND(data) ((data) >> 28)
+#define SSIP_PAYLOAD(data) ((data) & 0xfffffff)
+/* Commands */
+#define SSIP_SW_BREAK 0
+#define SSIP_BOOTINFO_REQ 1
+#define SSIP_BOOTINFO_RESP 2
+#define SSIP_WAKETEST_RESULT 3
+#define SSIP_START_TRANS 4
+#define SSIP_READY 5
+/* Payloads */
+#define SSIP_DATA_VERSION(data) ((data) & 0xff)
+#define SSIP_LOCAL_VERID 1
+#define SSIP_WAKETEST_OK 0
+#define SSIP_WAKETEST_FAILED 1
+#define SSIP_PDU_LENGTH(data) (((data) >> 8) & 0xffff)
+#define SSIP_MSG_ID(data) ((data) & 0xff)
+/* Generic Command */
+#define SSIP_CMD(cmd, payload) (((cmd) << 28) | ((payload) & 0xfffffff))
+/* Commands for the control channel */
+#define SSIP_BOOTINFO_REQ_CMD(ver) \
+ SSIP_CMD(SSIP_BOOTINFO_REQ, SSIP_DATA_VERSION(ver))
+#define SSIP_BOOTINFO_RESP_CMD(ver) \
+ SSIP_CMD(SSIP_BOOTINFO_RESP, SSIP_DATA_VERSION(ver))
+#define SSIP_START_TRANS_CMD(pdulen, id) \
+ SSIP_CMD(SSIP_START_TRANS, (((pdulen) << 8) | SSIP_MSG_ID(id)))
+#define SSIP_READY_CMD SSIP_CMD(SSIP_READY, 0)
+#define SSIP_SWBREAK_CMD SSIP_CMD(SSIP_SW_BREAK, 0)
+
+/* Main state machine states */
+enum {
+ INIT,
+ HANDSHAKE,
+ ACTIVE,
+};
+
+/* Send state machine states */
+enum {
+ SEND_IDLE,
+ WAIT4READY,
+ SEND_READY,
+ SENDING,
+ SENDING_SWBREAK,
+};
+
+/* Receive state machine states */
+enum {
+ RECV_IDLE,
+ RECV_READY,
+ RECEIVING,
+};
+
+/**
+ * struct ssi_protocol - SSI protocol (McSAAB) data
+ * @main_state: Main state machine
+ * @send_state: TX state machine
+ * @recv_state: RX state machine
+ * @waketest: Flag to follow wake line test
+ * @rxid: RX data id
+ * @txid: TX data id
+ * @txqueue_len: TX queue length
+ * @tx_wd: TX watchdog
+ * @rx_wd: RX watchdog
+ * @keep_alive: Workaround for SSI HW bug
+ * @lock: To serialize access to this struct
+ * @netdev: Phonet network device
+ * @txqueue: TX data queue
+ * @cmdqueue: Queue of free commands
+ * @cl: HSI client own reference
+ * @link: Link for ssip_list
+ * @tx_usecount: Refcount to keep track the slaves that use the wake line
+ * @channel_id_cmd: HSI channel id for command stream
+ * @channel_id_data: HSI channel id for data stream
+ */
+struct ssi_protocol {
+ unsigned int main_state;
+ unsigned int send_state;
+ unsigned int recv_state;
+ unsigned int waketest:1;
+ u8 rxid;
+ u8 txid;
+ unsigned int txqueue_len;
+ struct timer_list tx_wd;
+ struct timer_list rx_wd;
+ struct timer_list keep_alive; /* wake-up workaround */
+ spinlock_t lock;
+ struct net_device *netdev;
+ struct list_head txqueue;
+ struct list_head cmdqueue;
+ struct hsi_client *cl;
+ struct list_head link;
+ atomic_t tx_usecnt;
+ int channel_id_cmd;
+ int channel_id_data;
+};
+
+/* List of ssi protocol instances */
+static LIST_HEAD(ssip_list);
+
+static void ssip_rxcmd_complete(struct hsi_msg *msg);
+
+static inline void ssip_set_cmd(struct hsi_msg *msg, u32 cmd)
+{
+ u32 *data;
+
+ data = sg_virt(msg->sgt.sgl);
+ *data = cmd;
+}
+
+static inline u32 ssip_get_cmd(struct hsi_msg *msg)
+{
+ u32 *data;
+
+ data = sg_virt(msg->sgt.sgl);
+
+ return *data;
+}
+
+static void ssip_skb_to_msg(struct sk_buff *skb, struct hsi_msg *msg)
+{
+ skb_frag_t *frag;
+ struct scatterlist *sg;
+ int i;
+
+ BUG_ON(msg->sgt.nents != (unsigned int)(skb_shinfo(skb)->nr_frags + 1));
+
+ sg = msg->sgt.sgl;
+ sg_set_buf(sg, skb->data, skb_headlen(skb));
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ sg = sg_next(sg);
+ BUG_ON(!sg);
+ frag = &skb_shinfo(skb)->frags[i];
+ sg_set_page(sg, frag->page.p, frag->size, frag->page_offset);
+ }
+}
+
+static void ssip_free_data(struct hsi_msg *msg)
+{
+ struct sk_buff *skb;
+
+ skb = msg->context;
+ pr_debug("free data: msg %p context %p skb %p\n", msg, msg->context,
+ skb);
+ msg->destructor = NULL;
+ dev_kfree_skb(skb);
+ hsi_free_msg(msg);
+}
+
+static struct hsi_msg *ssip_alloc_data(struct ssi_protocol *ssi,
+ struct sk_buff *skb, gfp_t flags)
+{
+ struct hsi_msg *msg;
+
+ msg = hsi_alloc_msg(skb_shinfo(skb)->nr_frags + 1, flags);
+ if (!msg)
+ return NULL;
+ ssip_skb_to_msg(skb, msg);
+ msg->destructor = ssip_free_data;
+ msg->channel = ssi->channel_id_data;
+ msg->context = skb;
+
+ return msg;
+}
+
+static inline void ssip_release_cmd(struct hsi_msg *msg)
+{
+ struct ssi_protocol *ssi = hsi_client_drvdata(msg->cl);
+
+ dev_dbg(&msg->cl->device, "Release cmd 0x%08x\n", ssip_get_cmd(msg));
+ spin_lock_bh(&ssi->lock);
+ list_add_tail(&msg->link, &ssi->cmdqueue);
+ spin_unlock_bh(&ssi->lock);
+}
+
+static struct hsi_msg *ssip_claim_cmd(struct ssi_protocol *ssi)
+{
+ struct hsi_msg *msg;
+
+ BUG_ON(list_empty(&ssi->cmdqueue));
+
+ spin_lock_bh(&ssi->lock);
+ msg = list_first_entry(&ssi->cmdqueue, struct hsi_msg, link);
+ list_del(&msg->link);
+ spin_unlock_bh(&ssi->lock);
+ msg->destructor = ssip_release_cmd;
+
+ return msg;
+}
+
+static void ssip_free_cmds(struct ssi_protocol *ssi)
+{
+ struct hsi_msg *msg, *tmp;
+
+ list_for_each_entry_safe(msg, tmp, &ssi->cmdqueue, link) {
+ list_del(&msg->link);
+ msg->destructor = NULL;
+ kfree(sg_virt(msg->sgt.sgl));
+ hsi_free_msg(msg);
+ }
+}
+
+static int ssip_alloc_cmds(struct ssi_protocol *ssi)
+{
+ struct hsi_msg *msg;
+ u32 *buf;
+ unsigned int i;
+
+ for (i = 0; i < SSIP_MAX_CMDS; i++) {
+ msg = hsi_alloc_msg(1, GFP_KERNEL);
+ if (!msg)
+ goto out;
+ buf = kmalloc(sizeof(*buf), GFP_KERNEL);
+ if (!buf) {
+ hsi_free_msg(msg);
+ goto out;
+ }
+ sg_init_one(msg->sgt.sgl, buf, sizeof(*buf));
+ msg->channel = ssi->channel_id_cmd;
+ list_add_tail(&msg->link, &ssi->cmdqueue);
+ }
+
+ return 0;
+out:
+ ssip_free_cmds(ssi);
+
+ return -ENOMEM;
+}
+
+static void ssip_set_rxstate(struct ssi_protocol *ssi, unsigned int state)
+{
+ ssi->recv_state = state;
+ switch (state) {
+ case RECV_IDLE:
+ del_timer(&ssi->rx_wd);
+ if (ssi->send_state == SEND_IDLE)
+ del_timer(&ssi->keep_alive);
+ break;
+ case RECV_READY:
+ /* CMT speech workaround */
+ if (atomic_read(&ssi->tx_usecnt))
+ break;
+ /* Otherwise fall through */
+ case RECEIVING:
+ mod_timer(&ssi->keep_alive, jiffies +
+ msecs_to_jiffies(SSIP_KATOUT));
+ mod_timer(&ssi->rx_wd, jiffies + msecs_to_jiffies(SSIP_WDTOUT));
+ break;
+ default:
+ break;
+ }
+}
+
+static void ssip_set_txstate(struct ssi_protocol *ssi, unsigned int state)
+{
+ ssi->send_state = state;
+ switch (state) {
+ case SEND_IDLE:
+ case SEND_READY:
+ del_timer(&ssi->tx_wd);
+ if (ssi->recv_state == RECV_IDLE)
+ del_timer(&ssi->keep_alive);
+ break;
+ case WAIT4READY:
+ case SENDING:
+ case SENDING_SWBREAK:
+ mod_timer(&ssi->keep_alive,
+ jiffies + msecs_to_jiffies(SSIP_KATOUT));
+ mod_timer(&ssi->tx_wd, jiffies + msecs_to_jiffies(SSIP_WDTOUT));
+ break;
+ default:
+ break;
+ }
+}
+
+struct hsi_client *ssip_slave_get_master(struct hsi_client *slave)
+{
+ struct hsi_client *master = ERR_PTR(-ENODEV);
+ struct ssi_protocol *ssi;
+
+ list_for_each_entry(ssi, &ssip_list, link)
+ if (slave->device.parent == ssi->cl->device.parent) {
+ master = ssi->cl;
+ break;
+ }
+
+ return master;
+}
+EXPORT_SYMBOL_GPL(ssip_slave_get_master);
+
+int ssip_slave_start_tx(struct hsi_client *master)
+{
+ struct ssi_protocol *ssi = hsi_client_drvdata(master);
+
+ dev_dbg(&master->device, "start TX %d\n", atomic_read(&ssi->tx_usecnt));
+ spin_lock_bh(&ssi->lock);
+ if (ssi->send_state == SEND_IDLE) {
+ ssip_set_txstate(ssi, WAIT4READY);
+ hsi_start_tx(master);
+ }
+ spin_unlock_bh(&ssi->lock);
+ atomic_inc(&ssi->tx_usecnt);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ssip_slave_start_tx);
+
+int ssip_slave_stop_tx(struct hsi_client *master)
+{
+ struct ssi_protocol *ssi = hsi_client_drvdata(master);
+
+ WARN_ON_ONCE(atomic_read(&ssi->tx_usecnt) == 0);
+
+ if (atomic_dec_and_test(&ssi->tx_usecnt)) {
+ spin_lock_bh(&ssi->lock);
+ if ((ssi->send_state == SEND_READY) ||
+ (ssi->send_state == WAIT4READY)) {
+ ssip_set_txstate(ssi, SEND_IDLE);
+ hsi_stop_tx(master);
+ }
+ spin_unlock_bh(&ssi->lock);
+ }
+ dev_dbg(&master->device, "stop TX %d\n", atomic_read(&ssi->tx_usecnt));
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ssip_slave_stop_tx);
+
+int ssip_slave_running(struct hsi_client *master)
+{
+ struct ssi_protocol *ssi = hsi_client_drvdata(master);
+ return netif_running(ssi->netdev);
+}
+EXPORT_SYMBOL_GPL(ssip_slave_running);
+
+static void ssip_reset(struct hsi_client *cl)
+{
+ struct ssi_protocol *ssi = hsi_client_drvdata(cl);
+ struct list_head *head, *tmp;
+ struct hsi_msg *msg;
+
+ if (netif_running(ssi->netdev))
+ netif_carrier_off(ssi->netdev);
+ hsi_flush(cl);
+ spin_lock_bh(&ssi->lock);
+ if (ssi->send_state != SEND_IDLE)
+ hsi_stop_tx(cl);
+ if (ssi->waketest)
+ ssi_waketest(cl, 0);
+ del_timer(&ssi->rx_wd);
+ del_timer(&ssi->tx_wd);
+ del_timer(&ssi->keep_alive);
+ ssi->main_state = 0;
+ ssi->send_state = 0;
+ ssi->recv_state = 0;
+ ssi->waketest = 0;
+ ssi->rxid = 0;
+ ssi->txid = 0;
+ list_for_each_safe(head, tmp, &ssi->txqueue) {
+ msg = list_entry(head, struct hsi_msg, link);
+ dev_dbg(&cl->device, "Pending TX data\n");
+ list_del(head);
+ ssip_free_data(msg);
+ }
+ ssi->txqueue_len = 0;
+ spin_unlock_bh(&ssi->lock);
+}
+
+static void ssip_dump_state(struct hsi_client *cl)
+{
+ struct ssi_protocol *ssi = hsi_client_drvdata(cl);
+ struct hsi_msg *msg;
+
+ spin_lock_bh(&ssi->lock);
+ dev_err(&cl->device, "Main state: %d\n", ssi->main_state);
+ dev_err(&cl->device, "Recv state: %d\n", ssi->recv_state);
+ dev_err(&cl->device, "Send state: %d\n", ssi->send_state);
+ dev_err(&cl->device, "CMT %s\n", (ssi->main_state == ACTIVE) ?
+ "Online" : "Offline");
+ dev_err(&cl->device, "Wake test %d\n", ssi->waketest);
+ dev_err(&cl->device, "Data RX id: %d\n", ssi->rxid);
+ dev_err(&cl->device, "Data TX id: %d\n", ssi->txid);
+
+ list_for_each_entry(msg, &ssi->txqueue, link)
+ dev_err(&cl->device, "pending TX data (%p)\n", msg);
+ spin_unlock_bh(&ssi->lock);
+}
+
+static void ssip_error(struct hsi_client *cl)
+{
+ struct ssi_protocol *ssi = hsi_client_drvdata(cl);
+ struct hsi_msg *msg;
+
+ ssip_dump_state(cl);
+ ssip_reset(cl);
+ msg = ssip_claim_cmd(ssi);
+ msg->complete = ssip_rxcmd_complete;
+ hsi_async_read(cl, msg);
+}
+
+static void ssip_keep_alive(unsigned long data)
+{
+ struct hsi_client *cl = (struct hsi_client *)data;
+ struct ssi_protocol *ssi = hsi_client_drvdata(cl);
+
+ dev_dbg(&cl->device, "Keep alive kick in: m(%d) r(%d) s(%d)\n",
+ ssi->main_state, ssi->recv_state, ssi->send_state);
+
+ spin_lock(&ssi->lock);
+ if (ssi->recv_state == RECV_IDLE)
+ switch (ssi->send_state) {
+ case SEND_READY:
+ if (atomic_read(&ssi->tx_usecnt) == 0)
+ break;
+ /*
+ * Fall through. Workaround for cmt-speech
+ * in that case we relay on audio timers.
+ */
+ case SEND_IDLE:
+ spin_unlock(&ssi->lock);
+ return;
+ }
+ mod_timer(&ssi->keep_alive, jiffies + msecs_to_jiffies(SSIP_KATOUT));
+ spin_unlock(&ssi->lock);
+}
+
+static void ssip_wd(unsigned long data)
+{
+ struct hsi_client *cl = (struct hsi_client *)data;
+
+ dev_err(&cl->device, "Watchdog trigerred\n");
+ ssip_error(cl);
+}
+
+static void ssip_send_bootinfo_req_cmd(struct hsi_client *cl)
+{
+ struct ssi_protocol *ssi = hsi_client_drvdata(cl);
+ struct hsi_msg *msg;
+
+ dev_dbg(&cl->device, "Issuing BOOT INFO REQ command\n");
+ msg = ssip_claim_cmd(ssi);
+ ssip_set_cmd(msg, SSIP_BOOTINFO_REQ_CMD(SSIP_LOCAL_VERID));
+ msg->complete = ssip_release_cmd;
+ hsi_async_write(cl, msg);
+ dev_dbg(&cl->device, "Issuing RX command\n");
+ msg = ssip_claim_cmd(ssi);
+ msg->complete = ssip_rxcmd_complete;
+ hsi_async_read(cl, msg);
+}
+
+static void ssip_start_rx(struct hsi_client *cl)
+{
+ struct ssi_protocol *ssi = hsi_client_drvdata(cl);
+ struct hsi_msg *msg;
+
+ dev_dbg(&cl->device, "RX start M(%d) R(%d)\n", ssi->main_state,
+ ssi->recv_state);
+ spin_lock(&ssi->lock);
+ /*
+ * We can have two UP events in a row due to a short low
+ * high transition. Therefore we need to ignore the sencond UP event.
+ */
+ if ((ssi->main_state != ACTIVE) || (ssi->recv_state == RECV_READY)) {
+ if (ssi->main_state == INIT) {
+ ssi->main_state = HANDSHAKE;
+ spin_unlock(&ssi->lock);
+ ssip_send_bootinfo_req_cmd(cl);
+ } else {
+ spin_unlock(&ssi->lock);
+ }
+ return;
+ }
+ ssip_set_rxstate(ssi, RECV_READY);
+ spin_unlock(&ssi->lock);
+
+ msg = ssip_claim_cmd(ssi);
+ ssip_set_cmd(msg, SSIP_READY_CMD);
+ msg->complete = ssip_release_cmd;
+ dev_dbg(&cl->device, "Send READY\n");
+ hsi_async_write(cl, msg);
+}
+
+static void ssip_stop_rx(struct hsi_client *cl)
+{
+ struct ssi_protocol *ssi = hsi_client_drvdata(cl);
+
+ dev_dbg(&cl->device, "RX stop M(%d)\n", ssi->main_state);
+ spin_lock(&ssi->lock);
+ if (likely(ssi->main_state == ACTIVE))
+ ssip_set_rxstate(ssi, RECV_IDLE);
+ spin_unlock(&ssi->lock);
+}
+
+static void ssip_free_strans(struct hsi_msg *msg)
+{
+ ssip_free_data(msg->context);
+ ssip_release_cmd(msg);
+}
+
+static void ssip_strans_complete(struct hsi_msg *msg)
+{
+ struct hsi_client *cl = msg->cl;
+ struct ssi_protocol *ssi = hsi_client_drvdata(cl);
+ struct hsi_msg *data;
+
+ data = msg->context;
+ ssip_release_cmd(msg);
+ spin_lock(&ssi->lock);
+ ssip_set_txstate(ssi, SENDING);
+ spin_unlock(&ssi->lock);
+ hsi_async_write(cl, data);
+}
+
+static int ssip_xmit(struct hsi_client *cl)
+{
+ struct ssi_protocol *ssi = hsi_client_drvdata(cl);
+ struct hsi_msg *msg, *dmsg;
+ struct sk_buff *skb;
+
+ spin_lock_bh(&ssi->lock);
+ if (list_empty(&ssi->txqueue)) {
+ spin_unlock_bh(&ssi->lock);
+ return 0;
+ }
+ dmsg = list_first_entry(&ssi->txqueue, struct hsi_msg, link);
+ list_del(&dmsg->link);
+ ssi->txqueue_len--;
+ spin_unlock_bh(&ssi->lock);
+
+ msg = ssip_claim_cmd(ssi);
+ skb = dmsg->context;
+ msg->context = dmsg;
+ msg->complete = ssip_strans_complete;
+ msg->destructor = ssip_free_strans;
+
+ spin_lock_bh(&ssi->lock);
+ ssip_set_cmd(msg, SSIP_START_TRANS_CMD(SSIP_BYTES_TO_FRAMES(skb->len),
+ ssi->txid));
+ ssi->txid++;
+ ssip_set_txstate(ssi, SENDING);
+ spin_unlock_bh(&ssi->lock);
+
+ dev_dbg(&cl->device, "Send STRANS (%d frames)\n",
+ SSIP_BYTES_TO_FRAMES(skb->len));
+
+ return hsi_async_write(cl, msg);
+}
+
+/* In soft IRQ context */
+static void ssip_pn_rx(struct sk_buff *skb)
+{
+ struct net_device *dev = skb->dev;
+
+ if (unlikely(!netif_running(dev))) {
+ dev_dbg(&dev->dev, "Drop RX packet\n");
+ dev->stats.rx_dropped++;
+ dev_kfree_skb(skb);
+ return;
+ }
+ if (unlikely(!pskb_may_pull(skb, SSIP_MIN_PN_HDR))) {
+ dev_dbg(&dev->dev, "Error drop RX packet\n");
+ dev->stats.rx_errors++;
+ dev->stats.rx_length_errors++;
+ dev_kfree_skb(skb);
+ return;
+ }
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += skb->len;
+
+ /* length field is exchanged in network byte order */
+ ((u16 *)skb->data)[2] = ntohs(((u16 *)skb->data)[2]);
+ dev_dbg(&dev->dev, "RX length fixed (%04x -> %u)\n",
+ ((u16 *)skb->data)[2], ntohs(((u16 *)skb->data)[2]));
+
+ skb->protocol = htons(ETH_P_PHONET);
+ skb_reset_mac_header(skb);
+ __skb_pull(skb, 1);
+ netif_rx(skb);
+}
+
+static void ssip_rx_data_complete(struct hsi_msg *msg)
+{
+ struct hsi_client *cl = msg->cl;
+ struct ssi_protocol *ssi = hsi_client_drvdata(cl);
+ struct sk_buff *skb;
+
+ if (msg->status == HSI_STATUS_ERROR) {
+ dev_err(&cl->device, "RX data error\n");
+ ssip_free_data(msg);
+ ssip_error(cl);
+ return;
+ }
+ del_timer(&ssi->rx_wd); /* FIXME: Revisit */
+ skb = msg->context;
+ ssip_pn_rx(skb);
+ hsi_free_msg(msg);
+}
+
+static void ssip_rx_bootinforeq(struct hsi_client *cl, u32 cmd)
+{
+ struct ssi_protocol *ssi = hsi_client_drvdata(cl);
+ struct hsi_msg *msg;
+
+ /* Workaroud: Ignore CMT Loader message leftover */
+ if (cmd == SSIP_CMT_LOADER_SYNC)
+ return;
+
+ switch (ssi->main_state) {
+ case ACTIVE:
+ dev_err(&cl->device, "Boot info req on active state\n");
+ ssip_error(cl);
+ /* Fall through */
+ case INIT:
+ spin_lock(&ssi->lock);
+ ssi->main_state = HANDSHAKE;
+ if (!ssi->waketest) {
+ ssi->waketest = 1;
+ ssi_waketest(cl, 1); /* FIXME: To be removed */
+ }
+ /* Start boot handshake watchdog */
+ mod_timer(&ssi->tx_wd, jiffies + msecs_to_jiffies(SSIP_WDTOUT));
+ spin_unlock(&ssi->lock);
+ dev_dbg(&cl->device, "Send BOOTINFO_RESP\n");
+ if (SSIP_DATA_VERSION(cmd) != SSIP_LOCAL_VERID)
+ dev_warn(&cl->device, "boot info req verid mismatch\n");
+ msg = ssip_claim_cmd(ssi);
+ ssip_set_cmd(msg, SSIP_BOOTINFO_RESP_CMD(SSIP_LOCAL_VERID));
+ msg->complete = ssip_release_cmd;
+ hsi_async_write(cl, msg);
+ break;
+ case HANDSHAKE:
+ /* Ignore */
+ break;
+ default:
+ dev_dbg(&cl->device, "Wrong state M(%d)\n", ssi->main_state);
+ break;
+ }
+}
+
+static void ssip_rx_bootinforesp(struct hsi_client *cl, u32 cmd)
+{
+ struct ssi_protocol *ssi = hsi_client_drvdata(cl);
+
+ if (SSIP_DATA_VERSION(cmd) != SSIP_LOCAL_VERID)
+ dev_warn(&cl->device, "boot info resp verid mismatch\n");
+
+ spin_lock(&ssi->lock);
+ if (ssi->main_state != ACTIVE)
+ /* Use tx_wd as a boot watchdog in non ACTIVE state */
+ mod_timer(&ssi->tx_wd, jiffies + msecs_to_jiffies(SSIP_WDTOUT));
+ else
+ dev_dbg(&cl->device, "boot info resp ignored M(%d)\n",
+ ssi->main_state);
+ spin_unlock(&ssi->lock);
+}
+
+static void ssip_rx_waketest(struct hsi_client *cl, u32 cmd)
+{
+ struct ssi_protocol *ssi = hsi_client_drvdata(cl);
+ unsigned int wkres = SSIP_PAYLOAD(cmd);
+
+ spin_lock(&ssi->lock);
+ if (ssi->main_state != HANDSHAKE) {
+ dev_dbg(&cl->device, "wake lines test ignored M(%d)\n",
+ ssi->main_state);
+ spin_unlock(&ssi->lock);
+ return;
+ }
+ if (ssi->waketest) {
+ ssi->waketest = 0;
+ ssi_waketest(cl, 0); /* FIXME: To be removed */
+ }
+ ssi->main_state = ACTIVE;
+ del_timer(&ssi->tx_wd); /* Stop boot handshake timer */
+ spin_unlock(&ssi->lock);
+
+ dev_notice(&cl->device, "WAKELINES TEST %s\n",
+ wkres & SSIP_WAKETEST_FAILED ? "FAILED" : "OK");
+ if (wkres & SSIP_WAKETEST_FAILED) {
+ ssip_error(cl);
+ return;
+ }
+ dev_dbg(&cl->device, "CMT is ONLINE\n");
+ netif_wake_queue(ssi->netdev);
+ netif_carrier_on(ssi->netdev);
+}
+
+static void ssip_rx_ready(struct hsi_client *cl)
+{
+ struct ssi_protocol *ssi = hsi_client_drvdata(cl);
+
+ spin_lock(&ssi->lock);
+ if (unlikely(ssi->main_state != ACTIVE)) {
+ dev_dbg(&cl->device, "READY on wrong state: S(%d) M(%d)\n",
+ ssi->send_state, ssi->main_state);
+ spin_unlock(&ssi->lock);
+ return;
+ }
+ if (ssi->send_state != WAIT4READY) {
+ dev_dbg(&cl->device, "Ignore spurious READY command\n");
+ spin_unlock(&ssi->lock);
+ return;
+ }
+ ssip_set_txstate(ssi, SEND_READY);
+ spin_unlock(&ssi->lock);
+ ssip_xmit(cl);
+}
+
+static void ssip_rx_strans(struct hsi_client *cl, u32 cmd)
+{
+ struct ssi_protocol *ssi = hsi_client_drvdata(cl);
+ struct sk_buff *skb;
+ struct hsi_msg *msg;
+ int len = SSIP_PDU_LENGTH(cmd);
+
+ dev_dbg(&cl->device, "RX strans: %d frames\n", len);
+ spin_lock(&ssi->lock);
+ if (unlikely(ssi->main_state != ACTIVE)) {
+ dev_err(&cl->device, "START TRANS wrong state: S(%d) M(%d)\n",
+ ssi->send_state, ssi->main_state);
+ spin_unlock(&ssi->lock);
+ return;
+ }
+ ssip_set_rxstate(ssi, RECEIVING);
+ if (unlikely(SSIP_MSG_ID(cmd) != ssi->rxid)) {
+ dev_err(&cl->device, "START TRANS id %d expeceted %d\n",
+ SSIP_MSG_ID(cmd), ssi->rxid);
+ spin_unlock(&ssi->lock);
+ goto out1;
+ }
+ ssi->rxid++;
+ spin_unlock(&ssi->lock);
+ skb = netdev_alloc_skb(ssi->netdev, len * 4);
+ if (unlikely(!skb)) {
+ dev_err(&cl->device, "No memory for rx skb\n");
+ goto out1;
+ }
+ skb->dev = ssi->netdev;
+ skb_put(skb, len * 4);
+ msg = ssip_alloc_data(ssi, skb, GFP_ATOMIC);
+ if (unlikely(!msg)) {
+ dev_err(&cl->device, "No memory for RX data msg\n");
+ goto out2;
+ }
+ msg->complete = ssip_rx_data_complete;
+ hsi_async_read(cl, msg);
+
+ return;
+out2:
+ dev_kfree_skb(skb);
+out1:
+ ssip_error(cl);
+}
+
+static void ssip_rxcmd_complete(struct hsi_msg *msg)
+{
+ struct hsi_client *cl = msg->cl;
+ u32 cmd = ssip_get_cmd(msg);
+ unsigned int cmdid = SSIP_COMMAND(cmd);
+
+ if (msg->status == HSI_STATUS_ERROR) {
+ dev_err(&cl->device, "RX error detected\n");
+ ssip_release_cmd(msg);
+ ssip_error(cl);
+ return;
+ }
+ hsi_async_read(cl, msg);
+ dev_dbg(&cl->device, "RX cmd: 0x%08x\n", cmd);
+ switch (cmdid) {
+ case SSIP_SW_BREAK:
+ /* Ignored */
+ break;
+ case SSIP_BOOTINFO_REQ:
+ ssip_rx_bootinforeq(cl, cmd);
+ break;
+ case SSIP_BOOTINFO_RESP:
+ ssip_rx_bootinforesp(cl, cmd);
+ break;
+ case SSIP_WAKETEST_RESULT:
+ ssip_rx_waketest(cl, cmd);
+ break;
+ case SSIP_START_TRANS:
+ ssip_rx_strans(cl, cmd);
+ break;
+ case SSIP_READY:
+ ssip_rx_ready(cl);
+ break;
+ default:
+ dev_warn(&cl->device, "command 0x%08x not supported\n", cmd);
+ break;
+ }
+}
+
+static void ssip_swbreak_complete(struct hsi_msg *msg)
+{
+ struct hsi_client *cl = msg->cl;
+ struct ssi_protocol *ssi = hsi_client_drvdata(cl);
+
+ ssip_release_cmd(msg);
+ spin_lock(&ssi->lock);
+ if (list_empty(&ssi->txqueue)) {
+ if (atomic_read(&ssi->tx_usecnt)) {
+ ssip_set_txstate(ssi, SEND_READY);
+ } else {
+ ssip_set_txstate(ssi, SEND_IDLE);
+ hsi_stop_tx(cl);
+ }
+ spin_unlock(&ssi->lock);
+ } else {
+ spin_unlock(&ssi->lock);
+ ssip_xmit(cl);
+ }
+ netif_wake_queue(ssi->netdev);
+}
+
+static void ssip_tx_data_complete(struct hsi_msg *msg)
+{
+ struct hsi_client *cl = msg->cl;
+ struct ssi_protocol *ssi = hsi_client_drvdata(cl);
+ struct hsi_msg *cmsg;
+
+ if (msg->status == HSI_STATUS_ERROR) {
+ dev_err(&cl->device, "TX data error\n");
+ ssip_error(cl);
+ goto out;
+ }
+ spin_lock(&ssi->lock);
+ if (list_empty(&ssi->txqueue)) {
+ ssip_set_txstate(ssi, SENDING_SWBREAK);
+ spin_unlock(&ssi->lock);
+ cmsg = ssip_claim_cmd(ssi);
+ ssip_set_cmd(cmsg, SSIP_SWBREAK_CMD);
+ cmsg->complete = ssip_swbreak_complete;
+ dev_dbg(&cl->device, "Send SWBREAK\n");
+ hsi_async_write(cl, cmsg);
+ } else {
+ spin_unlock(&ssi->lock);
+ ssip_xmit(cl);
+ }
+out:
+ ssip_free_data(msg);
+}
+
+void ssip_port_event(struct hsi_client *cl, unsigned long event)
+{
+ switch (event) {
+ case HSI_EVENT_START_RX:
+ ssip_start_rx(cl);
+ break;
+ case HSI_EVENT_STOP_RX:
+ ssip_stop_rx(cl);
+ break;
+ default:
+ return;
+ }
+}
+
+static int ssip_pn_open(struct net_device *dev)
+{
+ struct hsi_client *cl = to_hsi_client(dev->dev.parent);
+ struct ssi_protocol *ssi = hsi_client_drvdata(cl);
+ int err;
+
+ err = hsi_claim_port(cl, 1);
+ if (err < 0) {
+ dev_err(&cl->device, "SSI port already claimed\n");
+ return err;
+ }
+ err = hsi_register_port_event(cl, ssip_port_event);
+ if (err < 0) {
+ dev_err(&cl->device, "Register HSI port event failed (%d)\n",
+ err);
+ return err;
+ }
+ dev_dbg(&cl->device, "Configuring SSI port\n");
+ hsi_setup(cl);
+ spin_lock_bh(&ssi->lock);
+ if (!ssi->waketest) {
+ ssi->waketest = 1;
+ ssi_waketest(cl, 1); /* FIXME: To be removed */
+ }
+ ssi->main_state = INIT;
+ spin_unlock_bh(&ssi->lock);
+
+ return 0;
+}
+
+static int ssip_pn_stop(struct net_device *dev)
+{
+ struct hsi_client *cl = to_hsi_client(dev->dev.parent);
+
+ ssip_reset(cl);
+ hsi_unregister_port_event(cl);
+ hsi_release_port(cl);
+
+ return 0;
+}
+
+static int ssip_pn_set_mtu(struct net_device *dev, int new_mtu)
+{
+ if (new_mtu > SSIP_MAX_MTU || new_mtu < PHONET_MIN_MTU)
+ return -EINVAL;
+ dev->mtu = new_mtu;
+
+ return 0;
+}
+
+static int ssip_pn_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct hsi_client *cl = to_hsi_client(dev->dev.parent);
+ struct ssi_protocol *ssi = hsi_client_drvdata(cl);
+ struct hsi_msg *msg;
+
+ if ((skb->protocol != htons(ETH_P_PHONET)) ||
+ (skb->len < SSIP_MIN_PN_HDR))
+ goto drop;
+ /* Pad to 32-bits - FIXME: Revisit*/
+ if ((skb->len & 3) && skb_pad(skb, 4 - (skb->len & 3)))
+ goto drop;
+
+ /*
+ * Modem sends Phonet messages over SSI with its own endianess...
+ * Assume that modem has the same endianess as we do.
+ */
+ if (skb_cow_head(skb, 0))
+ goto drop;
+
+ /* length field is exchanged in network byte order */
+ ((u16 *)skb->data)[2] = htons(((u16 *)skb->data)[2]);
+
+ msg = ssip_alloc_data(ssi, skb, GFP_ATOMIC);
+ if (!msg) {
+ dev_dbg(&cl->device, "Dropping tx data: No memory\n");
+ goto drop;
+ }
+ msg->complete = ssip_tx_data_complete;
+
+ spin_lock_bh(&ssi->lock);
+ if (unlikely(ssi->main_state != ACTIVE)) {
+ spin_unlock_bh(&ssi->lock);
+ dev_dbg(&cl->device, "Dropping tx data: CMT is OFFLINE\n");
+ goto drop2;
+ }
+ list_add_tail(&msg->link, &ssi->txqueue);
+ ssi->txqueue_len++;
+ if (dev->tx_queue_len < ssi->txqueue_len) {
+ dev_info(&cl->device, "TX queue full %d\n", ssi->txqueue_len);
+ netif_stop_queue(dev);
+ }
+ if (ssi->send_state == SEND_IDLE) {
+ ssip_set_txstate(ssi, WAIT4READY);
+ spin_unlock_bh(&ssi->lock);
+ dev_dbg(&cl->device, "Start TX qlen %d\n", ssi->txqueue_len);
+ hsi_start_tx(cl);
+ } else if (ssi->send_state == SEND_READY) {
+ /* Needed for cmt-speech workaround */
+ dev_dbg(&cl->device, "Start TX on SEND READY qlen %d\n",
+ ssi->txqueue_len);
+ spin_unlock_bh(&ssi->lock);
+ ssip_xmit(cl);
+ } else {
+ spin_unlock_bh(&ssi->lock);
+ }
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += skb->len;
+
+ return 0;
+drop2:
+ hsi_free_msg(msg);
+drop:
+ dev->stats.tx_dropped++;
+ dev_kfree_skb(skb);
+
+ return 0;
+}
+
+/* CMT reset event handler */
+void ssip_reset_event(struct hsi_client *master)
+{
+ struct ssi_protocol *ssi = hsi_client_drvdata(master);
+ dev_err(&ssi->cl->device, "CMT reset detected!\n");
+ ssip_error(ssi->cl);
+}
+EXPORT_SYMBOL_GPL(ssip_reset_event);
+
+static const struct net_device_ops ssip_pn_ops = {
+ .ndo_open = ssip_pn_open,
+ .ndo_stop = ssip_pn_stop,
+ .ndo_start_xmit = ssip_pn_xmit,
+ .ndo_change_mtu = ssip_pn_set_mtu,
+};
+
+static void ssip_pn_setup(struct net_device *dev)
+{
+ dev->features = 0;
+ dev->netdev_ops = &ssip_pn_ops;
+ dev->type = ARPHRD_PHONET;
+ dev->flags = IFF_POINTOPOINT | IFF_NOARP;
+ dev->mtu = SSIP_DEFAULT_MTU;
+ dev->hard_header_len = 1;
+ dev->dev_addr[0] = PN_MEDIA_SOS;
+ dev->addr_len = 1;
+ dev->tx_queue_len = SSIP_TXQUEUE_LEN;
+
+ dev->destructor = free_netdev;
+ dev->header_ops = &phonet_header_ops;
+}
+
+static int ssi_protocol_probe(struct device *dev)
+{
+ static const char ifname[] = "phonet%d";
+ struct hsi_client *cl = to_hsi_client(dev);
+ struct ssi_protocol *ssi;
+ int err;
+
+ ssi = kzalloc(sizeof(*ssi), GFP_KERNEL);
+ if (!ssi) {
+ dev_err(dev, "No memory for ssi protocol\n");
+ return -ENOMEM;
+ }
+
+ spin_lock_init(&ssi->lock);
+ init_timer_deferrable(&ssi->rx_wd);
+ init_timer_deferrable(&ssi->tx_wd);
+ init_timer(&ssi->keep_alive);
+ ssi->rx_wd.data = (unsigned long)cl;
+ ssi->rx_wd.function = ssip_wd;
+ ssi->tx_wd.data = (unsigned long)cl;
+ ssi->tx_wd.function = ssip_wd;
+ ssi->keep_alive.data = (unsigned long)cl;
+ ssi->keep_alive.function = ssip_keep_alive;
+ INIT_LIST_HEAD(&ssi->txqueue);
+ INIT_LIST_HEAD(&ssi->cmdqueue);
+ atomic_set(&ssi->tx_usecnt, 0);
+ hsi_client_set_drvdata(cl, ssi);
+ ssi->cl = cl;
+
+ ssi->channel_id_cmd = hsi_get_channel_id_by_name(cl, "mcsaab-control");
+ if (ssi->channel_id_cmd < 0) {
+ err = ssi->channel_id_cmd;
+ dev_err(dev, "Could not get cmd channel (%d)\n", err);
+ goto out;
+ }
+
+ ssi->channel_id_data = hsi_get_channel_id_by_name(cl, "mcsaab-data");
+ if (ssi->channel_id_data < 0) {
+ err = ssi->channel_id_data;
+ dev_err(dev, "Could not get data channel (%d)\n", err);
+ goto out;
+ }
+
+ err = ssip_alloc_cmds(ssi);
+ if (err < 0) {
+ dev_err(dev, "No memory for commands\n");
+ goto out;
+ }
+
+ ssi->netdev = alloc_netdev(0, ifname, ssip_pn_setup);
+ if (!ssi->netdev) {
+ dev_err(dev, "No memory for netdev\n");
+ err = -ENOMEM;
+ goto out1;
+ }
+
+ SET_NETDEV_DEV(ssi->netdev, dev);
+ netif_carrier_off(ssi->netdev);
+ err = register_netdev(ssi->netdev);
+ if (err < 0) {
+ dev_err(dev, "Register netdev failed (%d)\n", err);
+ goto out2;
+ }
+
+ list_add(&ssi->link, &ssip_list);
+
+ dev_dbg(dev, "channel configuration: cmd=%d, data=%d\n",
+ ssi->channel_id_cmd, ssi->channel_id_data);
+
+ return 0;
+out2:
+ free_netdev(ssi->netdev);
+out1:
+ ssip_free_cmds(ssi);
+out:
+ kfree(ssi);
+
+ return err;
+}
+
+static int ssi_protocol_remove(struct device *dev)
+{
+ struct hsi_client *cl = to_hsi_client(dev);
+ struct ssi_protocol *ssi = hsi_client_drvdata(cl);
+
+ list_del(&ssi->link);
+ unregister_netdev(ssi->netdev);
+ ssip_free_cmds(ssi);
+ hsi_client_set_drvdata(cl, NULL);
+ kfree(ssi);
+
+ return 0;
+}
+
+static struct hsi_client_driver ssip_driver = {
+ .driver = {
+ .name = "ssi-protocol",
+ .owner = THIS_MODULE,
+ .probe = ssi_protocol_probe,
+ .remove = ssi_protocol_remove,
+ },
+};
+
+static int __init ssip_init(void)
+{
+ pr_info("SSI protocol aka McSAAB added\n");
+
+ return hsi_register_client_driver(&ssip_driver);
+}
+module_init(ssip_init);
+
+static void __exit ssip_exit(void)
+{
+ hsi_unregister_client_driver(&ssip_driver);
+ pr_info("SSI protocol driver removed\n");
+}
+module_exit(ssip_exit);
+
+MODULE_ALIAS("hsi:ssi-protocol");
+MODULE_AUTHOR("Carlos Chinea <carlos.chinea@nokia.com>");
+MODULE_AUTHOR("Remi Denis-Courmont <remi.denis-courmont@nokia.com>");
+MODULE_DESCRIPTION("SSI protocol improved aka McSAAB");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hsi/controllers/Kconfig b/drivers/hsi/controllers/Kconfig
new file mode 100644
index 000000000000..6aba27808172
--- /dev/null
+++ b/drivers/hsi/controllers/Kconfig
@@ -0,0 +1,19 @@
+#
+# HSI controllers configuration
+#
+comment "HSI controllers"
+
+config OMAP_SSI
+ tristate "OMAP SSI hardware driver"
+ depends on HSI && OF && (ARCH_OMAP3 || (ARM && COMPILE_TEST))
+ ---help---
+ SSI is a legacy version of HSI. It is usually used to connect
+ an application engine with a cellular modem.
+ If you say Y here, you will enable the OMAP SSI hardware driver.
+
+ If unsure, say N.
+
+config OMAP_SSI_PORT
+ tristate
+ default m if OMAP_SSI=m
+ default y if OMAP_SSI=y
diff --git a/drivers/hsi/controllers/Makefile b/drivers/hsi/controllers/Makefile
new file mode 100644
index 000000000000..d2665cf9c545
--- /dev/null
+++ b/drivers/hsi/controllers/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for HSI controllers drivers
+#
+
+obj-$(CONFIG_OMAP_SSI) += omap_ssi.o
+obj-$(CONFIG_OMAP_SSI_PORT) += omap_ssi_port.o
diff --git a/drivers/hsi/controllers/omap_ssi.c b/drivers/hsi/controllers/omap_ssi.c
new file mode 100644
index 000000000000..0fc7a7fd0140
--- /dev/null
+++ b/drivers/hsi/controllers/omap_ssi.c
@@ -0,0 +1,625 @@
+/* OMAP SSI driver.
+ *
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ * Copyright (C) 2014 Sebastian Reichel <sre@kernel.org>
+ *
+ * Contact: Carlos Chinea <carlos.chinea@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/compiler.h>
+#include <linux/err.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/scatterlist.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/debugfs.h>
+#include <linux/pm_runtime.h>
+#include <linux/of_platform.h>
+#include <linux/hsi/hsi.h>
+#include <linux/idr.h>
+
+#include "omap_ssi_regs.h"
+#include "omap_ssi.h"
+
+/* For automatically allocated device IDs */
+static DEFINE_IDA(platform_omap_ssi_ida);
+
+#ifdef CONFIG_DEBUG_FS
+static int ssi_debug_show(struct seq_file *m, void *p __maybe_unused)
+{
+ struct hsi_controller *ssi = m->private;
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+ void __iomem *sys = omap_ssi->sys;
+
+ pm_runtime_get_sync(ssi->device.parent);
+ seq_printf(m, "REVISION\t: 0x%08x\n", readl(sys + SSI_REVISION_REG));
+ seq_printf(m, "SYSCONFIG\t: 0x%08x\n", readl(sys + SSI_SYSCONFIG_REG));
+ seq_printf(m, "SYSSTATUS\t: 0x%08x\n", readl(sys + SSI_SYSSTATUS_REG));
+ pm_runtime_put_sync(ssi->device.parent);
+
+ return 0;
+}
+
+static int ssi_debug_gdd_show(struct seq_file *m, void *p __maybe_unused)
+{
+ struct hsi_controller *ssi = m->private;
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+ void __iomem *gdd = omap_ssi->gdd;
+ void __iomem *sys = omap_ssi->sys;
+ int lch;
+
+ pm_runtime_get_sync(ssi->device.parent);
+
+ seq_printf(m, "GDD_MPU_STATUS\t: 0x%08x\n",
+ readl(sys + SSI_GDD_MPU_IRQ_STATUS_REG));
+ seq_printf(m, "GDD_MPU_ENABLE\t: 0x%08x\n\n",
+ readl(sys + SSI_GDD_MPU_IRQ_ENABLE_REG));
+ seq_printf(m, "HW_ID\t\t: 0x%08x\n",
+ readl(gdd + SSI_GDD_HW_ID_REG));
+ seq_printf(m, "PPORT_ID\t: 0x%08x\n",
+ readl(gdd + SSI_GDD_PPORT_ID_REG));
+ seq_printf(m, "MPORT_ID\t: 0x%08x\n",
+ readl(gdd + SSI_GDD_MPORT_ID_REG));
+ seq_printf(m, "TEST\t\t: 0x%08x\n",
+ readl(gdd + SSI_GDD_TEST_REG));
+ seq_printf(m, "GCR\t\t: 0x%08x\n",
+ readl(gdd + SSI_GDD_GCR_REG));
+
+ for (lch = 0; lch < SSI_MAX_GDD_LCH; lch++) {
+ seq_printf(m, "\nGDD LCH %d\n=========\n", lch);
+ seq_printf(m, "CSDP\t\t: 0x%04x\n",
+ readw(gdd + SSI_GDD_CSDP_REG(lch)));
+ seq_printf(m, "CCR\t\t: 0x%04x\n",
+ readw(gdd + SSI_GDD_CCR_REG(lch)));
+ seq_printf(m, "CICR\t\t: 0x%04x\n",
+ readw(gdd + SSI_GDD_CICR_REG(lch)));
+ seq_printf(m, "CSR\t\t: 0x%04x\n",
+ readw(gdd + SSI_GDD_CSR_REG(lch)));
+ seq_printf(m, "CSSA\t\t: 0x%08x\n",
+ readl(gdd + SSI_GDD_CSSA_REG(lch)));
+ seq_printf(m, "CDSA\t\t: 0x%08x\n",
+ readl(gdd + SSI_GDD_CDSA_REG(lch)));
+ seq_printf(m, "CEN\t\t: 0x%04x\n",
+ readw(gdd + SSI_GDD_CEN_REG(lch)));
+ seq_printf(m, "CSAC\t\t: 0x%04x\n",
+ readw(gdd + SSI_GDD_CSAC_REG(lch)));
+ seq_printf(m, "CDAC\t\t: 0x%04x\n",
+ readw(gdd + SSI_GDD_CDAC_REG(lch)));
+ seq_printf(m, "CLNK_CTRL\t: 0x%04x\n",
+ readw(gdd + SSI_GDD_CLNK_CTRL_REG(lch)));
+ }
+
+ pm_runtime_put_sync(ssi->device.parent);
+
+ return 0;
+}
+
+static int ssi_regs_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, ssi_debug_show, inode->i_private);
+}
+
+static int ssi_gdd_regs_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, ssi_debug_gdd_show, inode->i_private);
+}
+
+static const struct file_operations ssi_regs_fops = {
+ .open = ssi_regs_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static const struct file_operations ssi_gdd_regs_fops = {
+ .open = ssi_gdd_regs_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int __init ssi_debug_add_ctrl(struct hsi_controller *ssi)
+{
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+ struct dentry *dir;
+
+ /* SSI controller */
+ omap_ssi->dir = debugfs_create_dir(dev_name(&ssi->device), NULL);
+ if (IS_ERR(omap_ssi->dir))
+ return PTR_ERR(omap_ssi->dir);
+
+ debugfs_create_file("regs", S_IRUGO, omap_ssi->dir, ssi,
+ &ssi_regs_fops);
+ /* SSI GDD (DMA) */
+ dir = debugfs_create_dir("gdd", omap_ssi->dir);
+ if (IS_ERR(dir))
+ goto rback;
+ debugfs_create_file("regs", S_IRUGO, dir, ssi, &ssi_gdd_regs_fops);
+
+ return 0;
+rback:
+ debugfs_remove_recursive(omap_ssi->dir);
+
+ return PTR_ERR(dir);
+}
+
+static void ssi_debug_remove_ctrl(struct hsi_controller *ssi)
+{
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+
+ debugfs_remove_recursive(omap_ssi->dir);
+}
+#endif /* CONFIG_DEBUG_FS */
+
+/*
+ * FIXME: Horrible HACK needed until we remove the useless wakeline test
+ * in the CMT. To be removed !!!!
+ */
+void ssi_waketest(struct hsi_client *cl, unsigned int enable)
+{
+ struct hsi_port *port = hsi_get_port(cl);
+ struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
+ struct hsi_controller *ssi = to_hsi_controller(port->device.parent);
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+
+ omap_port->wktest = !!enable;
+ if (omap_port->wktest) {
+ pm_runtime_get_sync(ssi->device.parent);
+ writel_relaxed(SSI_WAKE(0),
+ omap_ssi->sys + SSI_SET_WAKE_REG(port->num));
+ } else {
+ writel_relaxed(SSI_WAKE(0),
+ omap_ssi->sys + SSI_CLEAR_WAKE_REG(port->num));
+ pm_runtime_put_sync(ssi->device.parent);
+ }
+}
+EXPORT_SYMBOL_GPL(ssi_waketest);
+
+static void ssi_gdd_complete(struct hsi_controller *ssi, unsigned int lch)
+{
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+ struct hsi_msg *msg = omap_ssi->gdd_trn[lch].msg;
+ struct hsi_port *port = to_hsi_port(msg->cl->device.parent);
+ struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
+ unsigned int dir;
+ u32 csr;
+ u32 val;
+
+ spin_lock(&omap_ssi->lock);
+
+ val = readl(omap_ssi->sys + SSI_GDD_MPU_IRQ_ENABLE_REG);
+ val &= ~SSI_GDD_LCH(lch);
+ writel_relaxed(val, omap_ssi->sys + SSI_GDD_MPU_IRQ_ENABLE_REG);
+
+ if (msg->ttype == HSI_MSG_READ) {
+ dir = DMA_FROM_DEVICE;
+ val = SSI_DATAAVAILABLE(msg->channel);
+ pm_runtime_put_sync(ssi->device.parent);
+ } else {
+ dir = DMA_TO_DEVICE;
+ val = SSI_DATAACCEPT(msg->channel);
+ /* Keep clocks reference for write pio event */
+ }
+ dma_unmap_sg(&ssi->device, msg->sgt.sgl, msg->sgt.nents, dir);
+ csr = readw(omap_ssi->gdd + SSI_GDD_CSR_REG(lch));
+ omap_ssi->gdd_trn[lch].msg = NULL; /* release GDD lch */
+ dev_dbg(&port->device, "DMA completed ch %d ttype %d\n",
+ msg->channel, msg->ttype);
+ spin_unlock(&omap_ssi->lock);
+ if (csr & SSI_CSR_TOUR) { /* Timeout error */
+ msg->status = HSI_STATUS_ERROR;
+ msg->actual_len = 0;
+ spin_lock(&omap_port->lock);
+ list_del(&msg->link); /* Dequeue msg */
+ spin_unlock(&omap_port->lock);
+ msg->complete(msg);
+ return;
+ }
+ spin_lock(&omap_port->lock);
+ val |= readl(omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0));
+ writel_relaxed(val, omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0));
+ spin_unlock(&omap_port->lock);
+
+ msg->status = HSI_STATUS_COMPLETED;
+ msg->actual_len = sg_dma_len(msg->sgt.sgl);
+}
+
+static void ssi_gdd_tasklet(unsigned long dev)
+{
+ struct hsi_controller *ssi = (struct hsi_controller *)dev;
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+ void __iomem *sys = omap_ssi->sys;
+ unsigned int lch;
+ u32 status_reg;
+
+ pm_runtime_get_sync(ssi->device.parent);
+
+ status_reg = readl(sys + SSI_GDD_MPU_IRQ_STATUS_REG);
+ for (lch = 0; lch < SSI_MAX_GDD_LCH; lch++) {
+ if (status_reg & SSI_GDD_LCH(lch))
+ ssi_gdd_complete(ssi, lch);
+ }
+ writel_relaxed(status_reg, sys + SSI_GDD_MPU_IRQ_STATUS_REG);
+ status_reg = readl(sys + SSI_GDD_MPU_IRQ_STATUS_REG);
+
+ pm_runtime_put_sync(ssi->device.parent);
+
+ if (status_reg)
+ tasklet_hi_schedule(&omap_ssi->gdd_tasklet);
+ else
+ enable_irq(omap_ssi->gdd_irq);
+
+}
+
+static irqreturn_t ssi_gdd_isr(int irq, void *ssi)
+{
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+
+ tasklet_hi_schedule(&omap_ssi->gdd_tasklet);
+ disable_irq_nosync(irq);
+
+ return IRQ_HANDLED;
+}
+
+static unsigned long ssi_get_clk_rate(struct hsi_controller *ssi)
+{
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+ unsigned long rate = clk_get_rate(omap_ssi->fck);
+ return rate;
+}
+
+static int __init ssi_get_iomem(struct platform_device *pd,
+ const char *name, void __iomem **pbase, dma_addr_t *phy)
+{
+ struct resource *mem;
+ struct resource *ioarea;
+ void __iomem *base;
+ struct hsi_controller *ssi = platform_get_drvdata(pd);
+
+ mem = platform_get_resource_byname(pd, IORESOURCE_MEM, name);
+ if (!mem) {
+ dev_err(&pd->dev, "IO memory region missing (%s)\n", name);
+ return -ENXIO;
+ }
+ ioarea = devm_request_mem_region(&ssi->device, mem->start,
+ resource_size(mem), dev_name(&pd->dev));
+ if (!ioarea) {
+ dev_err(&pd->dev, "%s IO memory region request failed\n",
+ mem->name);
+ return -ENXIO;
+ }
+ base = devm_ioremap(&ssi->device, mem->start, resource_size(mem));
+ if (!base) {
+ dev_err(&pd->dev, "%s IO remap failed\n", mem->name);
+ return -ENXIO;
+ }
+ *pbase = base;
+
+ if (phy)
+ *phy = mem->start;
+
+ return 0;
+}
+
+static int __init ssi_add_controller(struct hsi_controller *ssi,
+ struct platform_device *pd)
+{
+ struct omap_ssi_controller *omap_ssi;
+ int err;
+
+ omap_ssi = devm_kzalloc(&ssi->device, sizeof(*omap_ssi), GFP_KERNEL);
+ if (!omap_ssi) {
+ dev_err(&pd->dev, "not enough memory for omap ssi\n");
+ return -ENOMEM;
+ }
+
+ ssi->id = ida_simple_get(&platform_omap_ssi_ida, 0, 0, GFP_KERNEL);
+ if (ssi->id < 0) {
+ err = ssi->id;
+ goto out_err;
+ }
+
+ ssi->owner = THIS_MODULE;
+ ssi->device.parent = &pd->dev;
+ dev_set_name(&ssi->device, "ssi%d", ssi->id);
+ hsi_controller_set_drvdata(ssi, omap_ssi);
+ omap_ssi->dev = &ssi->device;
+ err = ssi_get_iomem(pd, "sys", &omap_ssi->sys, NULL);
+ if (err < 0)
+ goto out_err;
+ err = ssi_get_iomem(pd, "gdd", &omap_ssi->gdd, NULL);
+ if (err < 0)
+ goto out_err;
+ omap_ssi->gdd_irq = platform_get_irq_byname(pd, "gdd_mpu");
+ if (omap_ssi->gdd_irq < 0) {
+ dev_err(&pd->dev, "GDD IRQ resource missing\n");
+ err = omap_ssi->gdd_irq;
+ goto out_err;
+ }
+ tasklet_init(&omap_ssi->gdd_tasklet, ssi_gdd_tasklet,
+ (unsigned long)ssi);
+ err = devm_request_irq(&ssi->device, omap_ssi->gdd_irq, ssi_gdd_isr,
+ 0, "gdd_mpu", ssi);
+ if (err < 0) {
+ dev_err(&ssi->device, "Request GDD IRQ %d failed (%d)",
+ omap_ssi->gdd_irq, err);
+ goto out_err;
+ }
+
+ omap_ssi->port = devm_kzalloc(&ssi->device,
+ sizeof(struct omap_ssi_port *) * ssi->num_ports, GFP_KERNEL);
+ if (!omap_ssi->port) {
+ err = -ENOMEM;
+ goto out_err;
+ }
+
+ omap_ssi->fck = devm_clk_get(&ssi->device, "ssi_ssr_fck");
+ if (IS_ERR(omap_ssi->fck)) {
+ dev_err(&pd->dev, "Could not acquire clock \"ssi_ssr_fck\": %li\n",
+ PTR_ERR(omap_ssi->fck));
+ err = -ENODEV;
+ goto out_err;
+ }
+
+ /* TODO: find register, which can be used to detect context loss */
+ omap_ssi->get_loss = NULL;
+
+ omap_ssi->max_speed = UINT_MAX;
+ spin_lock_init(&omap_ssi->lock);
+ err = hsi_register_controller(ssi);
+
+ if (err < 0)
+ goto out_err;
+
+ return 0;
+
+out_err:
+ ida_simple_remove(&platform_omap_ssi_ida, ssi->id);
+ return err;
+}
+
+static int __init ssi_hw_init(struct hsi_controller *ssi)
+{
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+ unsigned int i;
+ u32 val;
+ int err;
+
+ err = pm_runtime_get_sync(ssi->device.parent);
+ if (err < 0) {
+ dev_err(&ssi->device, "runtime PM failed %d\n", err);
+ return err;
+ }
+ /* Reseting SSI controller */
+ writel_relaxed(SSI_SOFTRESET, omap_ssi->sys + SSI_SYSCONFIG_REG);
+ val = readl(omap_ssi->sys + SSI_SYSSTATUS_REG);
+ for (i = 0; ((i < 20) && !(val & SSI_RESETDONE)); i++) {
+ msleep(20);
+ val = readl(omap_ssi->sys + SSI_SYSSTATUS_REG);
+ }
+ if (!(val & SSI_RESETDONE)) {
+ dev_err(&ssi->device, "SSI HW reset failed\n");
+ pm_runtime_put_sync(ssi->device.parent);
+ return -EIO;
+ }
+ /* Reseting GDD */
+ writel_relaxed(SSI_SWRESET, omap_ssi->gdd + SSI_GDD_GRST_REG);
+ /* Get FCK rate in KHz */
+ omap_ssi->fck_rate = DIV_ROUND_CLOSEST(ssi_get_clk_rate(ssi), 1000);
+ dev_dbg(&ssi->device, "SSI fck rate %lu KHz\n", omap_ssi->fck_rate);
+ /* Set default PM settings */
+ val = SSI_AUTOIDLE | SSI_SIDLEMODE_SMART | SSI_MIDLEMODE_SMART;
+ writel_relaxed(val, omap_ssi->sys + SSI_SYSCONFIG_REG);
+ omap_ssi->sysconfig = val;
+ writel_relaxed(SSI_CLK_AUTOGATING_ON, omap_ssi->sys + SSI_GDD_GCR_REG);
+ omap_ssi->gdd_gcr = SSI_CLK_AUTOGATING_ON;
+ pm_runtime_put_sync(ssi->device.parent);
+
+ return 0;
+}
+
+static void ssi_remove_controller(struct hsi_controller *ssi)
+{
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+ int id = ssi->id;
+ tasklet_kill(&omap_ssi->gdd_tasklet);
+ hsi_unregister_controller(ssi);
+ ida_simple_remove(&platform_omap_ssi_ida, id);
+}
+
+static inline int ssi_of_get_available_ports_count(const struct device_node *np)
+{
+ struct device_node *child;
+ int num = 0;
+
+ for_each_available_child_of_node(np, child)
+ if (of_device_is_compatible(child, "ti,omap3-ssi-port"))
+ num++;
+
+ return num;
+}
+
+static int ssi_remove_ports(struct device *dev, void *c)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+
+ of_device_unregister(pdev);
+
+ return 0;
+}
+
+static int __init ssi_probe(struct platform_device *pd)
+{
+ struct platform_device *childpdev;
+ struct device_node *np = pd->dev.of_node;
+ struct device_node *child;
+ struct hsi_controller *ssi;
+ int err;
+ int num_ports;
+
+ if (!np) {
+ dev_err(&pd->dev, "missing device tree data\n");
+ return -EINVAL;
+ }
+
+ num_ports = ssi_of_get_available_ports_count(np);
+
+ ssi = hsi_alloc_controller(num_ports, GFP_KERNEL);
+ if (!ssi) {
+ dev_err(&pd->dev, "No memory for controller\n");
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(pd, ssi);
+
+ err = ssi_add_controller(ssi, pd);
+ if (err < 0)
+ goto out1;
+
+ pm_runtime_irq_safe(&pd->dev);
+ pm_runtime_enable(&pd->dev);
+
+ err = ssi_hw_init(ssi);
+ if (err < 0)
+ goto out2;
+#ifdef CONFIG_DEBUG_FS
+ err = ssi_debug_add_ctrl(ssi);
+ if (err < 0)
+ goto out2;
+#endif
+
+ for_each_available_child_of_node(np, child) {
+ if (!of_device_is_compatible(child, "ti,omap3-ssi-port"))
+ continue;
+
+ childpdev = of_platform_device_create(child, NULL, &pd->dev);
+ if (!childpdev) {
+ err = -ENODEV;
+ dev_err(&pd->dev, "failed to create ssi controller port\n");
+ goto out3;
+ }
+ }
+
+ dev_info(&pd->dev, "ssi controller %d initialized (%d ports)!\n",
+ ssi->id, num_ports);
+ return err;
+out3:
+ device_for_each_child(&pd->dev, NULL, ssi_remove_ports);
+out2:
+ ssi_remove_controller(ssi);
+out1:
+ platform_set_drvdata(pd, NULL);
+ pm_runtime_disable(&pd->dev);
+
+ return err;
+}
+
+static int __exit ssi_remove(struct platform_device *pd)
+{
+ struct hsi_controller *ssi = platform_get_drvdata(pd);
+
+#ifdef CONFIG_DEBUG_FS
+ ssi_debug_remove_ctrl(ssi);
+#endif
+ ssi_remove_controller(ssi);
+ platform_set_drvdata(pd, NULL);
+
+ pm_runtime_disable(&pd->dev);
+
+ /* cleanup of of_platform_populate() call */
+ device_for_each_child(&pd->dev, NULL, ssi_remove_ports);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_RUNTIME
+static int omap_ssi_runtime_suspend(struct device *dev)
+{
+ struct hsi_controller *ssi = dev_get_drvdata(dev);
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+
+ dev_dbg(dev, "runtime suspend!\n");
+
+ if (omap_ssi->get_loss)
+ omap_ssi->loss_count =
+ omap_ssi->get_loss(ssi->device.parent);
+
+ return 0;
+}
+
+static int omap_ssi_runtime_resume(struct device *dev)
+{
+ struct hsi_controller *ssi = dev_get_drvdata(dev);
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+
+ dev_dbg(dev, "runtime resume!\n");
+
+ if ((omap_ssi->get_loss) && (omap_ssi->loss_count ==
+ omap_ssi->get_loss(ssi->device.parent)))
+ return 0;
+
+ writel_relaxed(omap_ssi->gdd_gcr, omap_ssi->gdd + SSI_GDD_GCR_REG);
+
+ return 0;
+}
+
+static const struct dev_pm_ops omap_ssi_pm_ops = {
+ SET_RUNTIME_PM_OPS(omap_ssi_runtime_suspend, omap_ssi_runtime_resume,
+ NULL)
+};
+
+#define DEV_PM_OPS (&omap_ssi_pm_ops)
+#else
+#define DEV_PM_OPS NULL
+#endif
+
+#ifdef CONFIG_OF
+static const struct of_device_id omap_ssi_of_match[] = {
+ { .compatible = "ti,omap3-ssi", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, omap_ssi_of_match);
+#else
+#define omap_ssi_of_match NULL
+#endif
+
+static struct platform_driver ssi_pdriver = {
+ .remove = __exit_p(ssi_remove),
+ .driver = {
+ .name = "omap_ssi",
+ .owner = THIS_MODULE,
+ .pm = DEV_PM_OPS,
+ .of_match_table = omap_ssi_of_match,
+ },
+};
+
+module_platform_driver_probe(ssi_pdriver, ssi_probe);
+
+MODULE_ALIAS("platform:omap_ssi");
+MODULE_AUTHOR("Carlos Chinea <carlos.chinea@nokia.com>");
+MODULE_AUTHOR("Sebastian Reichel <sre@kernel.org>");
+MODULE_DESCRIPTION("Synchronous Serial Interface Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hsi/controllers/omap_ssi.h b/drivers/hsi/controllers/omap_ssi.h
new file mode 100644
index 000000000000..9d056417d88c
--- /dev/null
+++ b/drivers/hsi/controllers/omap_ssi.h
@@ -0,0 +1,166 @@
+/* OMAP SSI internal interface.
+ *
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ * Copyright (C) 2013 Sebastian Reichel
+ *
+ * Contact: Carlos Chinea <carlos.chinea@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef __LINUX_HSI_OMAP_SSI_H__
+#define __LINUX_HSI_OMAP_SSI_H__
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/hsi/hsi.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+
+#define SSI_MAX_CHANNELS 8
+#define SSI_MAX_GDD_LCH 8
+#define SSI_BYTES_TO_FRAMES(x) ((((x) - 1) >> 2) + 1)
+
+/**
+ * struct omap_ssm_ctx - OMAP synchronous serial module (TX/RX) context
+ * @mode: Bit transmission mode
+ * @channels: Number of channels
+ * @framesize: Frame size in bits
+ * @timeout: RX frame timeout
+ * @divisor: TX divider
+ * @arb_mode: Arbitration mode for TX frame (Round robin, priority)
+ */
+struct omap_ssm_ctx {
+ u32 mode;
+ u32 channels;
+ u32 frame_size;
+ union {
+ u32 timeout; /* Rx Only */
+ struct {
+ u32 arb_mode;
+ u32 divisor;
+ }; /* Tx only */
+ };
+};
+
+/**
+ * struct omap_ssi_port - OMAP SSI port data
+ * @dev: device associated to the port (HSI port)
+ * @pdev: platform device associated to the port
+ * @sst_dma: SSI transmitter physical base address
+ * @ssr_dma: SSI receiver physical base address
+ * @sst_base: SSI transmitter base address
+ * @ssr_base: SSI receiver base address
+ * @wk_lock: spin lock to serialize access to the wake lines
+ * @lock: Spin lock to serialize access to the SSI port
+ * @channels: Current number of channels configured (1,2,4 or 8)
+ * @txqueue: TX message queues
+ * @rxqueue: RX message queues
+ * @brkqueue: Queue of incoming HWBREAK requests (FRAME mode)
+ * @irq: IRQ number
+ * @wake_irq: IRQ number for incoming wake line (-1 if none)
+ * @wake_gpio: GPIO number for incoming wake line (-1 if none)
+ * @pio_tasklet: Bottom half for PIO transfers and events
+ * @wake_tasklet: Bottom half for incoming wake events
+ * @wkin_cken: Keep track of clock references due to the incoming wake line
+ * @wk_refcount: Reference count for output wake line
+ * @sys_mpu_enable: Context for the interrupt enable register for irq 0
+ * @sst: Context for the synchronous serial transmitter
+ * @ssr: Context for the synchronous serial receiver
+ */
+struct omap_ssi_port {
+ struct device *dev;
+ struct device *pdev;
+ dma_addr_t sst_dma;
+ dma_addr_t ssr_dma;
+ void __iomem *sst_base;
+ void __iomem *ssr_base;
+ spinlock_t wk_lock;
+ spinlock_t lock;
+ unsigned int channels;
+ struct list_head txqueue[SSI_MAX_CHANNELS];
+ struct list_head rxqueue[SSI_MAX_CHANNELS];
+ struct list_head brkqueue;
+ unsigned int irq;
+ int wake_irq;
+ int wake_gpio;
+ struct tasklet_struct pio_tasklet;
+ struct tasklet_struct wake_tasklet;
+ bool wktest:1; /* FIXME: HACK to be removed */
+ bool wkin_cken:1; /* Workaround */
+ unsigned int wk_refcount;
+ /* OMAP SSI port context */
+ u32 sys_mpu_enable; /* We use only one irq */
+ struct omap_ssm_ctx sst;
+ struct omap_ssm_ctx ssr;
+ u32 loss_count;
+ u32 port_id;
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *dir;
+#endif
+};
+
+/**
+ * struct gdd_trn - GDD transaction data
+ * @msg: Pointer to the HSI message being served
+ * @sg: Pointer to the current sg entry being served
+ */
+struct gdd_trn {
+ struct hsi_msg *msg;
+ struct scatterlist *sg;
+};
+
+/**
+ * struct omap_ssi_controller - OMAP SSI controller data
+ * @dev: device associated to the controller (HSI controller)
+ * @sys: SSI I/O base address
+ * @gdd: GDD I/O base address
+ * @fck: SSI functional clock
+ * @gdd_irq: IRQ line for GDD
+ * @gdd_tasklet: bottom half for DMA transfers
+ * @gdd_trn: Array of GDD transaction data for ongoing GDD transfers
+ * @lock: lock to serialize access to GDD
+ * @loss_count: To follow if we need to restore context or not
+ * @max_speed: Maximum TX speed (Kb/s) set by the clients.
+ * @sysconfig: SSI controller saved context
+ * @gdd_gcr: SSI GDD saved context
+ * @get_loss: Pointer to omap_pm_get_dev_context_loss_count, if any
+ * @port: Array of pointers of the ports of the controller
+ * @dir: Debugfs SSI root directory
+ */
+struct omap_ssi_controller {
+ struct device *dev;
+ void __iomem *sys;
+ void __iomem *gdd;
+ struct clk *fck;
+ unsigned int gdd_irq;
+ struct tasklet_struct gdd_tasklet;
+ struct gdd_trn gdd_trn[SSI_MAX_GDD_LCH];
+ spinlock_t lock;
+ unsigned long fck_rate;
+ u32 loss_count;
+ u32 max_speed;
+ /* OMAP SSI Controller context */
+ u32 sysconfig;
+ u32 gdd_gcr;
+ int (*get_loss)(struct device *dev);
+ struct omap_ssi_port **port;
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *dir;
+#endif
+};
+
+#endif /* __LINUX_HSI_OMAP_SSI_H__ */
diff --git a/drivers/hsi/controllers/omap_ssi_port.c b/drivers/hsi/controllers/omap_ssi_port.c
new file mode 100644
index 000000000000..b8693f0b27fe
--- /dev/null
+++ b/drivers/hsi/controllers/omap_ssi_port.c
@@ -0,0 +1,1399 @@
+/* OMAP SSI port driver.
+ *
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ * Copyright (C) 2014 Sebastian Reichel <sre@kernel.org>
+ *
+ * Contact: Carlos Chinea <carlos.chinea@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/pm_runtime.h>
+
+#include <linux/of_gpio.h>
+#include <linux/debugfs.h>
+
+#include "omap_ssi_regs.h"
+#include "omap_ssi.h"
+
+static inline int hsi_dummy_msg(struct hsi_msg *msg __maybe_unused)
+{
+ return 0;
+}
+
+static inline int hsi_dummy_cl(struct hsi_client *cl __maybe_unused)
+{
+ return 0;
+}
+
+static inline unsigned int ssi_wakein(struct hsi_port *port)
+{
+ struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
+ return gpio_get_value(omap_port->wake_gpio);
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void ssi_debug_remove_port(struct hsi_port *port)
+{
+ struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
+
+ debugfs_remove_recursive(omap_port->dir);
+}
+
+static int ssi_debug_port_show(struct seq_file *m, void *p __maybe_unused)
+{
+ struct hsi_port *port = m->private;
+ struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
+ struct hsi_controller *ssi = to_hsi_controller(port->device.parent);
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+ void __iomem *base = omap_ssi->sys;
+ unsigned int ch;
+
+ pm_runtime_get_sync(omap_port->pdev);
+ if (omap_port->wake_irq > 0)
+ seq_printf(m, "CAWAKE\t\t: %d\n", ssi_wakein(port));
+ seq_printf(m, "WAKE\t\t: 0x%08x\n",
+ readl(base + SSI_WAKE_REG(port->num)));
+ seq_printf(m, "MPU_ENABLE_IRQ%d\t: 0x%08x\n", 0,
+ readl(base + SSI_MPU_ENABLE_REG(port->num, 0)));
+ seq_printf(m, "MPU_STATUS_IRQ%d\t: 0x%08x\n", 0,
+ readl(base + SSI_MPU_STATUS_REG(port->num, 0)));
+ /* SST */
+ base = omap_port->sst_base;
+ seq_puts(m, "\nSST\n===\n");
+ seq_printf(m, "ID SST\t\t: 0x%08x\n",
+ readl(base + SSI_SST_ID_REG));
+ seq_printf(m, "MODE\t\t: 0x%08x\n",
+ readl(base + SSI_SST_MODE_REG));
+ seq_printf(m, "FRAMESIZE\t: 0x%08x\n",
+ readl(base + SSI_SST_FRAMESIZE_REG));
+ seq_printf(m, "DIVISOR\t\t: 0x%08x\n",
+ readl(base + SSI_SST_DIVISOR_REG));
+ seq_printf(m, "CHANNELS\t: 0x%08x\n",
+ readl(base + SSI_SST_CHANNELS_REG));
+ seq_printf(m, "ARBMODE\t\t: 0x%08x\n",
+ readl(base + SSI_SST_ARBMODE_REG));
+ seq_printf(m, "TXSTATE\t\t: 0x%08x\n",
+ readl(base + SSI_SST_TXSTATE_REG));
+ seq_printf(m, "BUFSTATE\t: 0x%08x\n",
+ readl(base + SSI_SST_BUFSTATE_REG));
+ seq_printf(m, "BREAK\t\t: 0x%08x\n",
+ readl(base + SSI_SST_BREAK_REG));
+ for (ch = 0; ch < omap_port->channels; ch++) {
+ seq_printf(m, "BUFFER_CH%d\t: 0x%08x\n", ch,
+ readl(base + SSI_SST_BUFFER_CH_REG(ch)));
+ }
+ /* SSR */
+ base = omap_port->ssr_base;
+ seq_puts(m, "\nSSR\n===\n");
+ seq_printf(m, "ID SSR\t\t: 0x%08x\n",
+ readl(base + SSI_SSR_ID_REG));
+ seq_printf(m, "MODE\t\t: 0x%08x\n",
+ readl(base + SSI_SSR_MODE_REG));
+ seq_printf(m, "FRAMESIZE\t: 0x%08x\n",
+ readl(base + SSI_SSR_FRAMESIZE_REG));
+ seq_printf(m, "CHANNELS\t: 0x%08x\n",
+ readl(base + SSI_SSR_CHANNELS_REG));
+ seq_printf(m, "TIMEOUT\t\t: 0x%08x\n",
+ readl(base + SSI_SSR_TIMEOUT_REG));
+ seq_printf(m, "RXSTATE\t\t: 0x%08x\n",
+ readl(base + SSI_SSR_RXSTATE_REG));
+ seq_printf(m, "BUFSTATE\t: 0x%08x\n",
+ readl(base + SSI_SSR_BUFSTATE_REG));
+ seq_printf(m, "BREAK\t\t: 0x%08x\n",
+ readl(base + SSI_SSR_BREAK_REG));
+ seq_printf(m, "ERROR\t\t: 0x%08x\n",
+ readl(base + SSI_SSR_ERROR_REG));
+ seq_printf(m, "ERRORACK\t: 0x%08x\n",
+ readl(base + SSI_SSR_ERRORACK_REG));
+ for (ch = 0; ch < omap_port->channels; ch++) {
+ seq_printf(m, "BUFFER_CH%d\t: 0x%08x\n", ch,
+ readl(base + SSI_SSR_BUFFER_CH_REG(ch)));
+ }
+ pm_runtime_put_sync(omap_port->pdev);
+
+ return 0;
+}
+
+static int ssi_port_regs_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, ssi_debug_port_show, inode->i_private);
+}
+
+static const struct file_operations ssi_port_regs_fops = {
+ .open = ssi_port_regs_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int ssi_div_get(void *data, u64 *val)
+{
+ struct hsi_port *port = data;
+ struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
+
+ pm_runtime_get_sync(omap_port->pdev);
+ *val = readl(omap_port->sst_base + SSI_SST_DIVISOR_REG);
+ pm_runtime_put_sync(omap_port->pdev);
+
+ return 0;
+}
+
+static int ssi_div_set(void *data, u64 val)
+{
+ struct hsi_port *port = data;
+ struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
+
+ if (val > 127)
+ return -EINVAL;
+
+ pm_runtime_get_sync(omap_port->pdev);
+ writel(val, omap_port->sst_base + SSI_SST_DIVISOR_REG);
+ omap_port->sst.divisor = val;
+ pm_runtime_put_sync(omap_port->pdev);
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(ssi_sst_div_fops, ssi_div_get, ssi_div_set, "%llu\n");
+
+static int __init ssi_debug_add_port(struct omap_ssi_port *omap_port,
+ struct dentry *dir)
+{
+ struct hsi_port *port = to_hsi_port(omap_port->dev);
+
+ dir = debugfs_create_dir(dev_name(omap_port->dev), dir);
+ if (IS_ERR(dir))
+ return PTR_ERR(dir);
+ omap_port->dir = dir;
+ debugfs_create_file("regs", S_IRUGO, dir, port, &ssi_port_regs_fops);
+ dir = debugfs_create_dir("sst", dir);
+ if (IS_ERR(dir))
+ return PTR_ERR(dir);
+ debugfs_create_file("divisor", S_IRUGO | S_IWUSR, dir, port,
+ &ssi_sst_div_fops);
+
+ return 0;
+}
+#endif
+
+static int ssi_claim_lch(struct hsi_msg *msg)
+{
+
+ struct hsi_port *port = hsi_get_port(msg->cl);
+ struct hsi_controller *ssi = to_hsi_controller(port->device.parent);
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+ int lch;
+
+ for (lch = 0; lch < SSI_MAX_GDD_LCH; lch++)
+ if (!omap_ssi->gdd_trn[lch].msg) {
+ omap_ssi->gdd_trn[lch].msg = msg;
+ omap_ssi->gdd_trn[lch].sg = msg->sgt.sgl;
+ return lch;
+ }
+
+ return -EBUSY;
+}
+
+static int ssi_start_dma(struct hsi_msg *msg, int lch)
+{
+ struct hsi_port *port = hsi_get_port(msg->cl);
+ struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
+ struct hsi_controller *ssi = to_hsi_controller(port->device.parent);
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+ void __iomem *gdd = omap_ssi->gdd;
+ int err;
+ u16 csdp;
+ u16 ccr;
+ u32 s_addr;
+ u32 d_addr;
+ u32 tmp;
+
+ if (msg->ttype == HSI_MSG_READ) {
+ err = dma_map_sg(&ssi->device, msg->sgt.sgl, msg->sgt.nents,
+ DMA_FROM_DEVICE);
+ if (err < 0) {
+ dev_dbg(&ssi->device, "DMA map SG failed !\n");
+ return err;
+ }
+ csdp = SSI_DST_BURST_4x32_BIT | SSI_DST_MEMORY_PORT |
+ SSI_SRC_SINGLE_ACCESS0 | SSI_SRC_PERIPHERAL_PORT |
+ SSI_DATA_TYPE_S32;
+ ccr = msg->channel + 0x10 + (port->num * 8); /* Sync */
+ ccr |= SSI_DST_AMODE_POSTINC | SSI_SRC_AMODE_CONST |
+ SSI_CCR_ENABLE;
+ s_addr = omap_port->ssr_dma +
+ SSI_SSR_BUFFER_CH_REG(msg->channel);
+ d_addr = sg_dma_address(msg->sgt.sgl);
+ } else {
+ err = dma_map_sg(&ssi->device, msg->sgt.sgl, msg->sgt.nents,
+ DMA_TO_DEVICE);
+ if (err < 0) {
+ dev_dbg(&ssi->device, "DMA map SG failed !\n");
+ return err;
+ }
+ csdp = SSI_SRC_BURST_4x32_BIT | SSI_SRC_MEMORY_PORT |
+ SSI_DST_SINGLE_ACCESS0 | SSI_DST_PERIPHERAL_PORT |
+ SSI_DATA_TYPE_S32;
+ ccr = (msg->channel + 1 + (port->num * 8)) & 0xf; /* Sync */
+ ccr |= SSI_SRC_AMODE_POSTINC | SSI_DST_AMODE_CONST |
+ SSI_CCR_ENABLE;
+ s_addr = sg_dma_address(msg->sgt.sgl);
+ d_addr = omap_port->sst_dma +
+ SSI_SST_BUFFER_CH_REG(msg->channel);
+ }
+ dev_dbg(&ssi->device, "lch %d cdsp %08x ccr %04x s_addr %08x d_addr %08x\n",
+ lch, csdp, ccr, s_addr, d_addr);
+
+ /* Hold clocks during the transfer */
+ pm_runtime_get_sync(omap_port->pdev);
+
+ writew_relaxed(csdp, gdd + SSI_GDD_CSDP_REG(lch));
+ writew_relaxed(SSI_BLOCK_IE | SSI_TOUT_IE, gdd + SSI_GDD_CICR_REG(lch));
+ writel_relaxed(d_addr, gdd + SSI_GDD_CDSA_REG(lch));
+ writel_relaxed(s_addr, gdd + SSI_GDD_CSSA_REG(lch));
+ writew_relaxed(SSI_BYTES_TO_FRAMES(msg->sgt.sgl->length),
+ gdd + SSI_GDD_CEN_REG(lch));
+
+ spin_lock_bh(&omap_ssi->lock);
+ tmp = readl(omap_ssi->sys + SSI_GDD_MPU_IRQ_ENABLE_REG);
+ tmp |= SSI_GDD_LCH(lch);
+ writel_relaxed(tmp, omap_ssi->sys + SSI_GDD_MPU_IRQ_ENABLE_REG);
+ spin_unlock_bh(&omap_ssi->lock);
+ writew(ccr, gdd + SSI_GDD_CCR_REG(lch));
+ msg->status = HSI_STATUS_PROCEEDING;
+
+ return 0;
+}
+
+static int ssi_start_pio(struct hsi_msg *msg)
+{
+ struct hsi_port *port = hsi_get_port(msg->cl);
+ struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
+ struct hsi_controller *ssi = to_hsi_controller(port->device.parent);
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+ u32 val;
+
+ pm_runtime_get_sync(omap_port->pdev);
+ if (msg->ttype == HSI_MSG_WRITE) {
+ val = SSI_DATAACCEPT(msg->channel);
+ /* Hold clocks for pio writes */
+ pm_runtime_get_sync(omap_port->pdev);
+ } else {
+ val = SSI_DATAAVAILABLE(msg->channel) | SSI_ERROROCCURED;
+ }
+ dev_dbg(&port->device, "Single %s transfer\n",
+ msg->ttype ? "write" : "read");
+ val |= readl(omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0));
+ writel(val, omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0));
+ pm_runtime_put_sync(omap_port->pdev);
+ msg->actual_len = 0;
+ msg->status = HSI_STATUS_PROCEEDING;
+
+ return 0;
+}
+
+static int ssi_start_transfer(struct list_head *queue)
+{
+ struct hsi_msg *msg;
+ int lch = -1;
+
+ if (list_empty(queue))
+ return 0;
+ msg = list_first_entry(queue, struct hsi_msg, link);
+ if (msg->status != HSI_STATUS_QUEUED)
+ return 0;
+ if ((msg->sgt.nents) && (msg->sgt.sgl->length > sizeof(u32)))
+ lch = ssi_claim_lch(msg);
+ if (lch >= 0)
+ return ssi_start_dma(msg, lch);
+ else
+ return ssi_start_pio(msg);
+}
+
+static int ssi_async_break(struct hsi_msg *msg)
+{
+ struct hsi_port *port = hsi_get_port(msg->cl);
+ struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
+ struct hsi_controller *ssi = to_hsi_controller(port->device.parent);
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+ int err = 0;
+ u32 tmp;
+
+ pm_runtime_get_sync(omap_port->pdev);
+ if (msg->ttype == HSI_MSG_WRITE) {
+ if (omap_port->sst.mode != SSI_MODE_FRAME) {
+ err = -EINVAL;
+ goto out;
+ }
+ writel(1, omap_port->sst_base + SSI_SST_BREAK_REG);
+ msg->status = HSI_STATUS_COMPLETED;
+ msg->complete(msg);
+ } else {
+ if (omap_port->ssr.mode != SSI_MODE_FRAME) {
+ err = -EINVAL;
+ goto out;
+ }
+ spin_lock_bh(&omap_port->lock);
+ tmp = readl(omap_ssi->sys +
+ SSI_MPU_ENABLE_REG(port->num, 0));
+ writel(tmp | SSI_BREAKDETECTED,
+ omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0));
+ msg->status = HSI_STATUS_PROCEEDING;
+ list_add_tail(&msg->link, &omap_port->brkqueue);
+ spin_unlock_bh(&omap_port->lock);
+ }
+out:
+ pm_runtime_put_sync(omap_port->pdev);
+
+ return err;
+}
+
+static int ssi_async(struct hsi_msg *msg)
+{
+ struct hsi_port *port = hsi_get_port(msg->cl);
+ struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
+ struct list_head *queue;
+ int err = 0;
+
+ BUG_ON(!msg);
+
+ if (msg->sgt.nents > 1)
+ return -ENOSYS; /* TODO: Add sg support */
+
+ if (msg->break_frame)
+ return ssi_async_break(msg);
+
+ if (msg->ttype) {
+ BUG_ON(msg->channel >= omap_port->sst.channels);
+ queue = &omap_port->txqueue[msg->channel];
+ } else {
+ BUG_ON(msg->channel >= omap_port->ssr.channels);
+ queue = &omap_port->rxqueue[msg->channel];
+ }
+ msg->status = HSI_STATUS_QUEUED;
+ spin_lock_bh(&omap_port->lock);
+ list_add_tail(&msg->link, queue);
+ err = ssi_start_transfer(queue);
+ if (err < 0) {
+ list_del(&msg->link);
+ msg->status = HSI_STATUS_ERROR;
+ }
+ spin_unlock_bh(&omap_port->lock);
+ dev_dbg(&port->device, "msg status %d ttype %d ch %d\n",
+ msg->status, msg->ttype, msg->channel);
+
+ return err;
+}
+
+static u32 ssi_calculate_div(struct hsi_controller *ssi)
+{
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+ u32 tx_fckrate = (u32) omap_ssi->fck_rate;
+
+ /* / 2 : SSI TX clock is always half of the SSI functional clock */
+ tx_fckrate >>= 1;
+ /* Round down when tx_fckrate % omap_ssi->max_speed == 0 */
+ tx_fckrate--;
+ dev_dbg(&ssi->device, "TX div %d for fck_rate %lu Khz speed %d Kb/s\n",
+ tx_fckrate / omap_ssi->max_speed, omap_ssi->fck_rate,
+ omap_ssi->max_speed);
+
+ return tx_fckrate / omap_ssi->max_speed;
+}
+
+static void ssi_flush_queue(struct list_head *queue, struct hsi_client *cl)
+{
+ struct list_head *node, *tmp;
+ struct hsi_msg *msg;
+
+ list_for_each_safe(node, tmp, queue) {
+ msg = list_entry(node, struct hsi_msg, link);
+ if ((cl) && (cl != msg->cl))
+ continue;
+ list_del(node);
+ pr_debug("flush queue: ch %d, msg %p len %d type %d ctxt %p\n",
+ msg->channel, msg, msg->sgt.sgl->length,
+ msg->ttype, msg->context);
+ if (msg->destructor)
+ msg->destructor(msg);
+ else
+ hsi_free_msg(msg);
+ }
+}
+
+static int ssi_setup(struct hsi_client *cl)
+{
+ struct hsi_port *port = to_hsi_port(cl->device.parent);
+ struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
+ struct hsi_controller *ssi = to_hsi_controller(port->device.parent);
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+ void __iomem *sst = omap_port->sst_base;
+ void __iomem *ssr = omap_port->ssr_base;
+ u32 div;
+ u32 val;
+ int err = 0;
+
+ pm_runtime_get_sync(omap_port->pdev);
+ spin_lock_bh(&omap_port->lock);
+ if (cl->tx_cfg.speed)
+ omap_ssi->max_speed = cl->tx_cfg.speed;
+ div = ssi_calculate_div(ssi);
+ if (div > SSI_MAX_DIVISOR) {
+ dev_err(&cl->device, "Invalid TX speed %d Mb/s (div %d)\n",
+ cl->tx_cfg.speed, div);
+ err = -EINVAL;
+ goto out;
+ }
+ /* Set TX/RX module to sleep to stop TX/RX during cfg update */
+ writel_relaxed(SSI_MODE_SLEEP, sst + SSI_SST_MODE_REG);
+ writel_relaxed(SSI_MODE_SLEEP, ssr + SSI_SSR_MODE_REG);
+ /* Flush posted write */
+ val = readl(ssr + SSI_SSR_MODE_REG);
+ /* TX */
+ writel_relaxed(31, sst + SSI_SST_FRAMESIZE_REG);
+ writel_relaxed(div, sst + SSI_SST_DIVISOR_REG);
+ writel_relaxed(cl->tx_cfg.num_hw_channels, sst + SSI_SST_CHANNELS_REG);
+ writel_relaxed(cl->tx_cfg.arb_mode, sst + SSI_SST_ARBMODE_REG);
+ writel_relaxed(cl->tx_cfg.mode, sst + SSI_SST_MODE_REG);
+ /* RX */
+ writel_relaxed(31, ssr + SSI_SSR_FRAMESIZE_REG);
+ writel_relaxed(cl->rx_cfg.num_hw_channels, ssr + SSI_SSR_CHANNELS_REG);
+ writel_relaxed(0, ssr + SSI_SSR_TIMEOUT_REG);
+ /* Cleanup the break queue if we leave FRAME mode */
+ if ((omap_port->ssr.mode == SSI_MODE_FRAME) &&
+ (cl->rx_cfg.mode != SSI_MODE_FRAME))
+ ssi_flush_queue(&omap_port->brkqueue, cl);
+ writel_relaxed(cl->rx_cfg.mode, ssr + SSI_SSR_MODE_REG);
+ omap_port->channels = max(cl->rx_cfg.num_hw_channels,
+ cl->tx_cfg.num_hw_channels);
+ /* Shadow registering for OFF mode */
+ /* SST */
+ omap_port->sst.divisor = div;
+ omap_port->sst.frame_size = 31;
+ omap_port->sst.channels = cl->tx_cfg.num_hw_channels;
+ omap_port->sst.arb_mode = cl->tx_cfg.arb_mode;
+ omap_port->sst.mode = cl->tx_cfg.mode;
+ /* SSR */
+ omap_port->ssr.frame_size = 31;
+ omap_port->ssr.timeout = 0;
+ omap_port->ssr.channels = cl->rx_cfg.num_hw_channels;
+ omap_port->ssr.mode = cl->rx_cfg.mode;
+out:
+ spin_unlock_bh(&omap_port->lock);
+ pm_runtime_put_sync(omap_port->pdev);
+
+ return err;
+}
+
+static int ssi_flush(struct hsi_client *cl)
+{
+ struct hsi_port *port = hsi_get_port(cl);
+ struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
+ struct hsi_controller *ssi = to_hsi_controller(port->device.parent);
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+ struct hsi_msg *msg;
+ void __iomem *sst = omap_port->sst_base;
+ void __iomem *ssr = omap_port->ssr_base;
+ unsigned int i;
+ u32 err;
+
+ pm_runtime_get_sync(omap_port->pdev);
+ spin_lock_bh(&omap_port->lock);
+ /* Stop all DMA transfers */
+ for (i = 0; i < SSI_MAX_GDD_LCH; i++) {
+ msg = omap_ssi->gdd_trn[i].msg;
+ if (!msg || (port != hsi_get_port(msg->cl)))
+ continue;
+ writew_relaxed(0, omap_ssi->gdd + SSI_GDD_CCR_REG(i));
+ if (msg->ttype == HSI_MSG_READ)
+ pm_runtime_put_sync(omap_port->pdev);
+ omap_ssi->gdd_trn[i].msg = NULL;
+ }
+ /* Flush all SST buffers */
+ writel_relaxed(0, sst + SSI_SST_BUFSTATE_REG);
+ writel_relaxed(0, sst + SSI_SST_TXSTATE_REG);
+ /* Flush all SSR buffers */
+ writel_relaxed(0, ssr + SSI_SSR_RXSTATE_REG);
+ writel_relaxed(0, ssr + SSI_SSR_BUFSTATE_REG);
+ /* Flush all errors */
+ err = readl(ssr + SSI_SSR_ERROR_REG);
+ writel_relaxed(err, ssr + SSI_SSR_ERRORACK_REG);
+ /* Flush break */
+ writel_relaxed(0, ssr + SSI_SSR_BREAK_REG);
+ /* Clear interrupts */
+ writel_relaxed(0, omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0));
+ writel_relaxed(0xffffff00,
+ omap_ssi->sys + SSI_MPU_STATUS_REG(port->num, 0));
+ writel_relaxed(0, omap_ssi->sys + SSI_GDD_MPU_IRQ_ENABLE_REG);
+ writel(0xff, omap_ssi->sys + SSI_GDD_MPU_IRQ_STATUS_REG);
+ /* Dequeue all pending requests */
+ for (i = 0; i < omap_port->channels; i++) {
+ /* Release write clocks */
+ if (!list_empty(&omap_port->txqueue[i]))
+ pm_runtime_put_sync(omap_port->pdev);
+ ssi_flush_queue(&omap_port->txqueue[i], NULL);
+ ssi_flush_queue(&omap_port->rxqueue[i], NULL);
+ }
+ ssi_flush_queue(&omap_port->brkqueue, NULL);
+ spin_unlock_bh(&omap_port->lock);
+ pm_runtime_put_sync(omap_port->pdev);
+
+ return 0;
+}
+
+static int ssi_start_tx(struct hsi_client *cl)
+{
+ struct hsi_port *port = hsi_get_port(cl);
+ struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
+ struct hsi_controller *ssi = to_hsi_controller(port->device.parent);
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+
+ dev_dbg(&port->device, "Wake out high %d\n", omap_port->wk_refcount);
+
+ spin_lock_bh(&omap_port->wk_lock);
+ if (omap_port->wk_refcount++) {
+ spin_unlock_bh(&omap_port->wk_lock);
+ return 0;
+ }
+ pm_runtime_get_sync(omap_port->pdev); /* Grab clocks */
+ writel(SSI_WAKE(0), omap_ssi->sys + SSI_SET_WAKE_REG(port->num));
+ spin_unlock_bh(&omap_port->wk_lock);
+
+ return 0;
+}
+
+static int ssi_stop_tx(struct hsi_client *cl)
+{
+ struct hsi_port *port = hsi_get_port(cl);
+ struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
+ struct hsi_controller *ssi = to_hsi_controller(port->device.parent);
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+
+ dev_dbg(&port->device, "Wake out low %d\n", omap_port->wk_refcount);
+
+ spin_lock_bh(&omap_port->wk_lock);
+ BUG_ON(!omap_port->wk_refcount);
+ if (--omap_port->wk_refcount) {
+ spin_unlock_bh(&omap_port->wk_lock);
+ return 0;
+ }
+ writel(SSI_WAKE(0), omap_ssi->sys + SSI_CLEAR_WAKE_REG(port->num));
+ pm_runtime_put_sync(omap_port->pdev); /* Release clocks */
+ spin_unlock_bh(&omap_port->wk_lock);
+
+ return 0;
+}
+
+static void ssi_transfer(struct omap_ssi_port *omap_port,
+ struct list_head *queue)
+{
+ struct hsi_msg *msg;
+ int err = -1;
+
+ spin_lock_bh(&omap_port->lock);
+ while (err < 0) {
+ err = ssi_start_transfer(queue);
+ if (err < 0) {
+ msg = list_first_entry(queue, struct hsi_msg, link);
+ msg->status = HSI_STATUS_ERROR;
+ msg->actual_len = 0;
+ list_del(&msg->link);
+ spin_unlock_bh(&omap_port->lock);
+ msg->complete(msg);
+ spin_lock_bh(&omap_port->lock);
+ }
+ }
+ spin_unlock_bh(&omap_port->lock);
+}
+
+static void ssi_cleanup_queues(struct hsi_client *cl)
+{
+ struct hsi_port *port = hsi_get_port(cl);
+ struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
+ struct hsi_controller *ssi = to_hsi_controller(port->device.parent);
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+ struct hsi_msg *msg;
+ unsigned int i;
+ u32 rxbufstate = 0;
+ u32 txbufstate = 0;
+ u32 status = SSI_ERROROCCURED;
+ u32 tmp;
+
+ ssi_flush_queue(&omap_port->brkqueue, cl);
+ if (list_empty(&omap_port->brkqueue))
+ status |= SSI_BREAKDETECTED;
+
+ for (i = 0; i < omap_port->channels; i++) {
+ if (list_empty(&omap_port->txqueue[i]))
+ continue;
+ msg = list_first_entry(&omap_port->txqueue[i], struct hsi_msg,
+ link);
+ if ((msg->cl == cl) && (msg->status == HSI_STATUS_PROCEEDING)) {
+ txbufstate |= (1 << i);
+ status |= SSI_DATAACCEPT(i);
+ /* Release the clocks writes, also GDD ones */
+ pm_runtime_put_sync(omap_port->pdev);
+ }
+ ssi_flush_queue(&omap_port->txqueue[i], cl);
+ }
+ for (i = 0; i < omap_port->channels; i++) {
+ if (list_empty(&omap_port->rxqueue[i]))
+ continue;
+ msg = list_first_entry(&omap_port->rxqueue[i], struct hsi_msg,
+ link);
+ if ((msg->cl == cl) && (msg->status == HSI_STATUS_PROCEEDING)) {
+ rxbufstate |= (1 << i);
+ status |= SSI_DATAAVAILABLE(i);
+ }
+ ssi_flush_queue(&omap_port->rxqueue[i], cl);
+ /* Check if we keep the error detection interrupt armed */
+ if (!list_empty(&omap_port->rxqueue[i]))
+ status &= ~SSI_ERROROCCURED;
+ }
+ /* Cleanup write buffers */
+ tmp = readl(omap_port->sst_base + SSI_SST_BUFSTATE_REG);
+ tmp &= ~txbufstate;
+ writel_relaxed(tmp, omap_port->sst_base + SSI_SST_BUFSTATE_REG);
+ /* Cleanup read buffers */
+ tmp = readl(omap_port->ssr_base + SSI_SSR_BUFSTATE_REG);
+ tmp &= ~rxbufstate;
+ writel_relaxed(tmp, omap_port->ssr_base + SSI_SSR_BUFSTATE_REG);
+ /* Disarm and ack pending interrupts */
+ tmp = readl(omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0));
+ tmp &= ~status;
+ writel_relaxed(tmp, omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0));
+ writel_relaxed(status, omap_ssi->sys +
+ SSI_MPU_STATUS_REG(port->num, 0));
+}
+
+static void ssi_cleanup_gdd(struct hsi_controller *ssi, struct hsi_client *cl)
+{
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+ struct hsi_port *port = hsi_get_port(cl);
+ struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
+ struct hsi_msg *msg;
+ unsigned int i;
+ u32 val = 0;
+ u32 tmp;
+
+ for (i = 0; i < SSI_MAX_GDD_LCH; i++) {
+ msg = omap_ssi->gdd_trn[i].msg;
+ if ((!msg) || (msg->cl != cl))
+ continue;
+ writew_relaxed(0, omap_ssi->gdd + SSI_GDD_CCR_REG(i));
+ val |= (1 << i);
+ /*
+ * Clock references for write will be handled in
+ * ssi_cleanup_queues
+ */
+ if (msg->ttype == HSI_MSG_READ)
+ pm_runtime_put_sync(omap_port->pdev);
+ omap_ssi->gdd_trn[i].msg = NULL;
+ }
+ tmp = readl_relaxed(omap_ssi->sys + SSI_GDD_MPU_IRQ_ENABLE_REG);
+ tmp &= ~val;
+ writel_relaxed(tmp, omap_ssi->sys + SSI_GDD_MPU_IRQ_ENABLE_REG);
+ writel(val, omap_ssi->sys + SSI_GDD_MPU_IRQ_STATUS_REG);
+}
+
+static int ssi_set_port_mode(struct omap_ssi_port *omap_port, u32 mode)
+{
+ writel(mode, omap_port->sst_base + SSI_SST_MODE_REG);
+ writel(mode, omap_port->ssr_base + SSI_SSR_MODE_REG);
+ /* OCP barrier */
+ mode = readl(omap_port->ssr_base + SSI_SSR_MODE_REG);
+
+ return 0;
+}
+
+static int ssi_release(struct hsi_client *cl)
+{
+ struct hsi_port *port = hsi_get_port(cl);
+ struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
+ struct hsi_controller *ssi = to_hsi_controller(port->device.parent);
+
+ spin_lock_bh(&omap_port->lock);
+ pm_runtime_get_sync(omap_port->pdev);
+ /* Stop all the pending DMA requests for that client */
+ ssi_cleanup_gdd(ssi, cl);
+ /* Now cleanup all the queues */
+ ssi_cleanup_queues(cl);
+ pm_runtime_put_sync(omap_port->pdev);
+ /* If it is the last client of the port, do extra checks and cleanup */
+ if (port->claimed <= 1) {
+ /*
+ * Drop the clock reference for the incoming wake line
+ * if it is still kept high by the other side.
+ */
+ if (omap_port->wkin_cken) {
+ pm_runtime_put_sync(omap_port->pdev);
+ omap_port->wkin_cken = 0;
+ }
+ pm_runtime_get_sync(omap_port->pdev);
+ /* Stop any SSI TX/RX without a client */
+ ssi_set_port_mode(omap_port, SSI_MODE_SLEEP);
+ omap_port->sst.mode = SSI_MODE_SLEEP;
+ omap_port->ssr.mode = SSI_MODE_SLEEP;
+ pm_runtime_put_sync(omap_port->pdev);
+ WARN_ON(omap_port->wk_refcount != 0);
+ }
+ spin_unlock_bh(&omap_port->lock);
+
+ return 0;
+}
+
+
+
+static void ssi_error(struct hsi_port *port)
+{
+ struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
+ struct hsi_controller *ssi = to_hsi_controller(port->device.parent);
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+ struct hsi_msg *msg;
+ unsigned int i;
+ u32 err;
+ u32 val;
+ u32 tmp;
+
+ /* ACK error */
+ err = readl(omap_port->ssr_base + SSI_SSR_ERROR_REG);
+ dev_err(&port->device, "SSI error: 0x%02x\n", err);
+ if (!err) {
+ dev_dbg(&port->device, "spurious SSI error ignored!\n");
+ return;
+ }
+ spin_lock(&omap_ssi->lock);
+ /* Cancel all GDD read transfers */
+ for (i = 0, val = 0; i < SSI_MAX_GDD_LCH; i++) {
+ msg = omap_ssi->gdd_trn[i].msg;
+ if ((msg) && (msg->ttype == HSI_MSG_READ)) {
+ writew_relaxed(0, omap_ssi->gdd + SSI_GDD_CCR_REG(i));
+ val |= (1 << i);
+ omap_ssi->gdd_trn[i].msg = NULL;
+ }
+ }
+ tmp = readl(omap_ssi->sys + SSI_GDD_MPU_IRQ_ENABLE_REG);
+ tmp &= ~val;
+ writel_relaxed(tmp, omap_ssi->sys + SSI_GDD_MPU_IRQ_ENABLE_REG);
+ spin_unlock(&omap_ssi->lock);
+ /* Cancel all PIO read transfers */
+ spin_lock(&omap_port->lock);
+ tmp = readl(omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0));
+ tmp &= 0xfeff00ff; /* Disable error & all dataavailable interrupts */
+ writel_relaxed(tmp, omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0));
+ /* ACK error */
+ writel_relaxed(err, omap_port->ssr_base + SSI_SSR_ERRORACK_REG);
+ writel_relaxed(SSI_ERROROCCURED,
+ omap_ssi->sys + SSI_MPU_STATUS_REG(port->num, 0));
+ /* Signal the error all current pending read requests */
+ for (i = 0; i < omap_port->channels; i++) {
+ if (list_empty(&omap_port->rxqueue[i]))
+ continue;
+ msg = list_first_entry(&omap_port->rxqueue[i], struct hsi_msg,
+ link);
+ list_del(&msg->link);
+ msg->status = HSI_STATUS_ERROR;
+ spin_unlock(&omap_port->lock);
+ msg->complete(msg);
+ /* Now restart queued reads if any */
+ ssi_transfer(omap_port, &omap_port->rxqueue[i]);
+ spin_lock(&omap_port->lock);
+ }
+ spin_unlock(&omap_port->lock);
+}
+
+static void ssi_break_complete(struct hsi_port *port)
+{
+ struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
+ struct hsi_controller *ssi = to_hsi_controller(port->device.parent);
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+ struct hsi_msg *msg;
+ struct hsi_msg *tmp;
+ u32 val;
+
+ dev_dbg(&port->device, "HWBREAK received\n");
+
+ spin_lock(&omap_port->lock);
+ val = readl(omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0));
+ val &= ~SSI_BREAKDETECTED;
+ writel_relaxed(val, omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0));
+ writel_relaxed(0, omap_port->ssr_base + SSI_SSR_BREAK_REG);
+ writel(SSI_BREAKDETECTED,
+ omap_ssi->sys + SSI_MPU_STATUS_REG(port->num, 0));
+ spin_unlock(&omap_port->lock);
+
+ list_for_each_entry_safe(msg, tmp, &omap_port->brkqueue, link) {
+ msg->status = HSI_STATUS_COMPLETED;
+ spin_lock(&omap_port->lock);
+ list_del(&msg->link);
+ spin_unlock(&omap_port->lock);
+ msg->complete(msg);
+ }
+
+}
+
+static void ssi_pio_complete(struct hsi_port *port, struct list_head *queue)
+{
+ struct hsi_controller *ssi = to_hsi_controller(port->device.parent);
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+ struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
+ struct hsi_msg *msg;
+ u32 *buf;
+ u32 reg;
+ u32 val;
+
+ spin_lock(&omap_port->lock);
+ msg = list_first_entry(queue, struct hsi_msg, link);
+ if ((!msg->sgt.nents) || (!msg->sgt.sgl->length)) {
+ msg->actual_len = 0;
+ msg->status = HSI_STATUS_PENDING;
+ }
+ if (msg->ttype == HSI_MSG_WRITE)
+ val = SSI_DATAACCEPT(msg->channel);
+ else
+ val = SSI_DATAAVAILABLE(msg->channel);
+ if (msg->status == HSI_STATUS_PROCEEDING) {
+ buf = sg_virt(msg->sgt.sgl) + msg->actual_len;
+ if (msg->ttype == HSI_MSG_WRITE)
+ writel(*buf, omap_port->sst_base +
+ SSI_SST_BUFFER_CH_REG(msg->channel));
+ else
+ *buf = readl(omap_port->ssr_base +
+ SSI_SSR_BUFFER_CH_REG(msg->channel));
+ dev_dbg(&port->device, "ch %d ttype %d 0x%08x\n", msg->channel,
+ msg->ttype, *buf);
+ msg->actual_len += sizeof(*buf);
+ if (msg->actual_len >= msg->sgt.sgl->length)
+ msg->status = HSI_STATUS_COMPLETED;
+ /*
+ * Wait for the last written frame to be really sent before
+ * we call the complete callback
+ */
+ if ((msg->status == HSI_STATUS_PROCEEDING) ||
+ ((msg->status == HSI_STATUS_COMPLETED) &&
+ (msg->ttype == HSI_MSG_WRITE))) {
+ writel(val, omap_ssi->sys +
+ SSI_MPU_STATUS_REG(port->num, 0));
+ spin_unlock(&omap_port->lock);
+
+ return;
+ }
+
+ }
+ /* Transfer completed at this point */
+ reg = readl(omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0));
+ if (msg->ttype == HSI_MSG_WRITE) {
+ /* Release clocks for write transfer */
+ pm_runtime_put_sync(omap_port->pdev);
+ }
+ reg &= ~val;
+ writel_relaxed(reg, omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0));
+ writel_relaxed(val, omap_ssi->sys + SSI_MPU_STATUS_REG(port->num, 0));
+ list_del(&msg->link);
+ spin_unlock(&omap_port->lock);
+ msg->complete(msg);
+ ssi_transfer(omap_port, queue);
+}
+
+static void ssi_pio_tasklet(unsigned long ssi_port)
+{
+ struct hsi_port *port = (struct hsi_port *)ssi_port;
+ struct hsi_controller *ssi = to_hsi_controller(port->device.parent);
+ struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+ void __iomem *sys = omap_ssi->sys;
+ unsigned int ch;
+ u32 status_reg;
+
+ pm_runtime_get_sync(omap_port->pdev);
+ status_reg = readl(sys + SSI_MPU_STATUS_REG(port->num, 0));
+ status_reg &= readl(sys + SSI_MPU_ENABLE_REG(port->num, 0));
+
+ for (ch = 0; ch < omap_port->channels; ch++) {
+ if (status_reg & SSI_DATAACCEPT(ch))
+ ssi_pio_complete(port, &omap_port->txqueue[ch]);
+ if (status_reg & SSI_DATAAVAILABLE(ch))
+ ssi_pio_complete(port, &omap_port->rxqueue[ch]);
+ }
+ if (status_reg & SSI_BREAKDETECTED)
+ ssi_break_complete(port);
+ if (status_reg & SSI_ERROROCCURED)
+ ssi_error(port);
+
+ status_reg = readl(sys + SSI_MPU_STATUS_REG(port->num, 0));
+ status_reg &= readl(sys + SSI_MPU_ENABLE_REG(port->num, 0));
+ pm_runtime_put_sync(omap_port->pdev);
+
+ if (status_reg)
+ tasklet_hi_schedule(&omap_port->pio_tasklet);
+ else
+ enable_irq(omap_port->irq);
+}
+
+static irqreturn_t ssi_pio_isr(int irq, void *port)
+{
+ struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
+
+ tasklet_hi_schedule(&omap_port->pio_tasklet);
+ disable_irq_nosync(irq);
+
+ return IRQ_HANDLED;
+}
+
+static void ssi_wake_tasklet(unsigned long ssi_port)
+{
+ struct hsi_port *port = (struct hsi_port *)ssi_port;
+ struct hsi_controller *ssi = to_hsi_controller(port->device.parent);
+ struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+
+ if (ssi_wakein(port)) {
+ /**
+ * We can have a quick High-Low-High transition in the line.
+ * In such a case if we have long interrupt latencies,
+ * we can miss the low event or get twice a high event.
+ * This workaround will avoid breaking the clock reference
+ * count when such a situation ocurrs.
+ */
+ spin_lock(&omap_port->lock);
+ if (!omap_port->wkin_cken) {
+ omap_port->wkin_cken = 1;
+ pm_runtime_get_sync(omap_port->pdev);
+ }
+ spin_unlock(&omap_port->lock);
+ dev_dbg(&ssi->device, "Wake in high\n");
+ if (omap_port->wktest) { /* FIXME: HACK ! To be removed */
+ writel(SSI_WAKE(0),
+ omap_ssi->sys + SSI_SET_WAKE_REG(port->num));
+ }
+ hsi_event(port, HSI_EVENT_START_RX);
+ } else {
+ dev_dbg(&ssi->device, "Wake in low\n");
+ if (omap_port->wktest) { /* FIXME: HACK ! To be removed */
+ writel(SSI_WAKE(0),
+ omap_ssi->sys + SSI_CLEAR_WAKE_REG(port->num));
+ }
+ hsi_event(port, HSI_EVENT_STOP_RX);
+ spin_lock(&omap_port->lock);
+ if (omap_port->wkin_cken) {
+ pm_runtime_put_sync(omap_port->pdev);
+ omap_port->wkin_cken = 0;
+ }
+ spin_unlock(&omap_port->lock);
+ }
+}
+
+static irqreturn_t ssi_wake_isr(int irq __maybe_unused, void *ssi_port)
+{
+ struct omap_ssi_port *omap_port = hsi_port_drvdata(ssi_port);
+
+ tasklet_hi_schedule(&omap_port->wake_tasklet);
+
+ return IRQ_HANDLED;
+}
+
+static int __init ssi_port_irq(struct hsi_port *port,
+ struct platform_device *pd)
+{
+ struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
+ int err;
+
+ omap_port->irq = platform_get_irq(pd, 0);
+ if (omap_port->irq < 0) {
+ dev_err(&port->device, "Port IRQ resource missing\n");
+ return omap_port->irq;
+ }
+ tasklet_init(&omap_port->pio_tasklet, ssi_pio_tasklet,
+ (unsigned long)port);
+ err = devm_request_irq(&port->device, omap_port->irq, ssi_pio_isr,
+ 0, "mpu_irq0", port);
+ if (err < 0)
+ dev_err(&port->device, "Request IRQ %d failed (%d)\n",
+ omap_port->irq, err);
+ return err;
+}
+
+static int __init ssi_wake_irq(struct hsi_port *port,
+ struct platform_device *pd)
+{
+ struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
+ int cawake_irq;
+ int err;
+
+ if (omap_port->wake_gpio == -1) {
+ omap_port->wake_irq = -1;
+ return 0;
+ }
+
+ cawake_irq = gpio_to_irq(omap_port->wake_gpio);
+
+ omap_port->wake_irq = cawake_irq;
+ tasklet_init(&omap_port->wake_tasklet, ssi_wake_tasklet,
+ (unsigned long)port);
+ err = devm_request_irq(&port->device, cawake_irq, ssi_wake_isr,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "cawake", port);
+ if (err < 0)
+ dev_err(&port->device, "Request Wake in IRQ %d failed %d\n",
+ cawake_irq, err);
+ err = enable_irq_wake(cawake_irq);
+ if (err < 0)
+ dev_err(&port->device, "Enable wake on the wakeline in irq %d failed %d\n",
+ cawake_irq, err);
+
+ return err;
+}
+
+static void __init ssi_queues_init(struct omap_ssi_port *omap_port)
+{
+ unsigned int ch;
+
+ for (ch = 0; ch < SSI_MAX_CHANNELS; ch++) {
+ INIT_LIST_HEAD(&omap_port->txqueue[ch]);
+ INIT_LIST_HEAD(&omap_port->rxqueue[ch]);
+ }
+ INIT_LIST_HEAD(&omap_port->brkqueue);
+}
+
+static int __init ssi_port_get_iomem(struct platform_device *pd,
+ const char *name, void __iomem **pbase, dma_addr_t *phy)
+{
+ struct hsi_port *port = platform_get_drvdata(pd);
+ struct resource *mem;
+ struct resource *ioarea;
+ void __iomem *base;
+
+ mem = platform_get_resource_byname(pd, IORESOURCE_MEM, name);
+ if (!mem) {
+ dev_err(&pd->dev, "IO memory region missing (%s)\n", name);
+ return -ENXIO;
+ }
+ ioarea = devm_request_mem_region(&port->device, mem->start,
+ resource_size(mem), dev_name(&pd->dev));
+ if (!ioarea) {
+ dev_err(&pd->dev, "%s IO memory region request failed\n",
+ mem->name);
+ return -ENXIO;
+ }
+ base = devm_ioremap(&port->device, mem->start, resource_size(mem));
+ if (!base) {
+ dev_err(&pd->dev, "%s IO remap failed\n", mem->name);
+ return -ENXIO;
+ }
+ *pbase = base;
+
+ if (phy)
+ *phy = mem->start;
+
+ return 0;
+}
+
+static int __init ssi_port_probe(struct platform_device *pd)
+{
+ struct device_node *np = pd->dev.of_node;
+ struct hsi_port *port;
+ struct omap_ssi_port *omap_port;
+ struct hsi_controller *ssi = dev_get_drvdata(pd->dev.parent);
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+ u32 cawake_gpio = 0;
+ u32 port_id;
+ int err;
+
+ dev_dbg(&pd->dev, "init ssi port...\n");
+
+ err = ref_module(THIS_MODULE, ssi->owner);
+ if (err) {
+ dev_err(&pd->dev, "could not increment parent module refcount (err=%d)\n",
+ err);
+ return -ENODEV;
+ }
+
+ if (!ssi->port || !omap_ssi->port) {
+ dev_err(&pd->dev, "ssi controller not initialized!\n");
+ err = -ENODEV;
+ goto error;
+ }
+
+ /* get id of first uninitialized port in controller */
+ for (port_id = 0; port_id < ssi->num_ports && omap_ssi->port[port_id];
+ port_id++)
+ ;
+
+ if (port_id >= ssi->num_ports) {
+ dev_err(&pd->dev, "port id out of range!\n");
+ err = -ENODEV;
+ goto error;
+ }
+
+ port = ssi->port[port_id];
+
+ if (!np) {
+ dev_err(&pd->dev, "missing device tree data\n");
+ err = -EINVAL;
+ goto error;
+ }
+
+ cawake_gpio = of_get_named_gpio(np, "ti,ssi-cawake-gpio", 0);
+ if (cawake_gpio < 0) {
+ dev_err(&pd->dev, "DT data is missing cawake gpio (err=%d)\n",
+ cawake_gpio);
+ err = -ENODEV;
+ goto error;
+ }
+
+ err = devm_gpio_request_one(&port->device, cawake_gpio, GPIOF_DIR_IN,
+ "cawake");
+ if (err) {
+ dev_err(&pd->dev, "could not request cawake gpio (err=%d)!\n",
+ err);
+ err = -ENXIO;
+ goto error;
+ }
+
+ omap_port = devm_kzalloc(&port->device, sizeof(*omap_port), GFP_KERNEL);
+ if (!omap_port) {
+ err = -ENOMEM;
+ goto error;
+ }
+ omap_port->wake_gpio = cawake_gpio;
+ omap_port->pdev = &pd->dev;
+ omap_port->port_id = port_id;
+
+ /* initialize HSI port */
+ port->async = ssi_async;
+ port->setup = ssi_setup;
+ port->flush = ssi_flush;
+ port->start_tx = ssi_start_tx;
+ port->stop_tx = ssi_stop_tx;
+ port->release = ssi_release;
+ hsi_port_set_drvdata(port, omap_port);
+ omap_ssi->port[port_id] = omap_port;
+
+ platform_set_drvdata(pd, port);
+
+ err = ssi_port_get_iomem(pd, "tx", &omap_port->sst_base,
+ &omap_port->sst_dma);
+ if (err < 0)
+ goto error;
+ err = ssi_port_get_iomem(pd, "rx", &omap_port->ssr_base,
+ &omap_port->ssr_dma);
+ if (err < 0)
+ goto error;
+
+ err = ssi_port_irq(port, pd);
+ if (err < 0)
+ goto error;
+ err = ssi_wake_irq(port, pd);
+ if (err < 0)
+ goto error;
+
+ ssi_queues_init(omap_port);
+ spin_lock_init(&omap_port->lock);
+ spin_lock_init(&omap_port->wk_lock);
+ omap_port->dev = &port->device;
+
+ pm_runtime_irq_safe(omap_port->pdev);
+ pm_runtime_enable(omap_port->pdev);
+
+#ifdef CONFIG_DEBUG_FS
+ err = ssi_debug_add_port(omap_port, omap_ssi->dir);
+ if (err < 0) {
+ pm_runtime_disable(omap_port->pdev);
+ goto error;
+ }
+#endif
+
+ hsi_add_clients_from_dt(port, np);
+
+ dev_info(&pd->dev, "ssi port %u successfully initialized (cawake=%d)\n",
+ port_id, cawake_gpio);
+
+ return 0;
+
+error:
+ return err;
+}
+
+static int __exit ssi_port_remove(struct platform_device *pd)
+{
+ struct hsi_port *port = platform_get_drvdata(pd);
+ struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
+ struct hsi_controller *ssi = to_hsi_controller(port->device.parent);
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+
+#ifdef CONFIG_DEBUG_FS
+ ssi_debug_remove_port(port);
+#endif
+
+ hsi_port_unregister_clients(port);
+
+ tasklet_kill(&omap_port->wake_tasklet);
+ tasklet_kill(&omap_port->pio_tasklet);
+
+ port->async = hsi_dummy_msg;
+ port->setup = hsi_dummy_cl;
+ port->flush = hsi_dummy_cl;
+ port->start_tx = hsi_dummy_cl;
+ port->stop_tx = hsi_dummy_cl;
+ port->release = hsi_dummy_cl;
+
+ omap_ssi->port[omap_port->port_id] = NULL;
+ platform_set_drvdata(pd, NULL);
+ pm_runtime_disable(&pd->dev);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_RUNTIME
+static int ssi_save_port_ctx(struct omap_ssi_port *omap_port)
+{
+ struct hsi_port *port = to_hsi_port(omap_port->dev);
+ struct hsi_controller *ssi = to_hsi_controller(port->device.parent);
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+
+ omap_port->sys_mpu_enable = readl(omap_ssi->sys +
+ SSI_MPU_ENABLE_REG(port->num, 0));
+
+ return 0;
+}
+
+static int ssi_restore_port_ctx(struct omap_ssi_port *omap_port)
+{
+ struct hsi_port *port = to_hsi_port(omap_port->dev);
+ struct hsi_controller *ssi = to_hsi_controller(port->device.parent);
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+ void __iomem *base;
+
+ writel_relaxed(omap_port->sys_mpu_enable,
+ omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0));
+
+ /* SST context */
+ base = omap_port->sst_base;
+ writel_relaxed(omap_port->sst.frame_size, base + SSI_SST_FRAMESIZE_REG);
+ writel_relaxed(omap_port->sst.channels, base + SSI_SST_CHANNELS_REG);
+ writel_relaxed(omap_port->sst.arb_mode, base + SSI_SST_ARBMODE_REG);
+
+ /* SSR context */
+ base = omap_port->ssr_base;
+ writel_relaxed(omap_port->ssr.frame_size, base + SSI_SSR_FRAMESIZE_REG);
+ writel_relaxed(omap_port->ssr.channels, base + SSI_SSR_CHANNELS_REG);
+ writel_relaxed(omap_port->ssr.timeout, base + SSI_SSR_TIMEOUT_REG);
+
+ return 0;
+}
+
+static int ssi_restore_port_mode(struct omap_ssi_port *omap_port)
+{
+ u32 mode;
+
+ writel_relaxed(omap_port->sst.mode,
+ omap_port->sst_base + SSI_SST_MODE_REG);
+ writel_relaxed(omap_port->ssr.mode,
+ omap_port->ssr_base + SSI_SSR_MODE_REG);
+ /* OCP barrier */
+ mode = readl(omap_port->ssr_base + SSI_SSR_MODE_REG);
+
+ return 0;
+}
+
+static int ssi_restore_divisor(struct omap_ssi_port *omap_port)
+{
+ writel_relaxed(omap_port->sst.divisor,
+ omap_port->sst_base + SSI_SST_DIVISOR_REG);
+
+ return 0;
+}
+
+static int omap_ssi_port_runtime_suspend(struct device *dev)
+{
+ struct hsi_port *port = dev_get_drvdata(dev);
+ struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
+ struct hsi_controller *ssi = to_hsi_controller(port->device.parent);
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+
+ dev_dbg(dev, "port runtime suspend!\n");
+
+ ssi_set_port_mode(omap_port, SSI_MODE_SLEEP);
+ if (omap_ssi->get_loss)
+ omap_port->loss_count =
+ omap_ssi->get_loss(ssi->device.parent);
+ ssi_save_port_ctx(omap_port);
+
+ return 0;
+}
+
+static int omap_ssi_port_runtime_resume(struct device *dev)
+{
+ struct hsi_port *port = dev_get_drvdata(dev);
+ struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
+ struct hsi_controller *ssi = to_hsi_controller(port->device.parent);
+ struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+
+ dev_dbg(dev, "port runtime resume!\n");
+
+ if ((omap_ssi->get_loss) && (omap_port->loss_count ==
+ omap_ssi->get_loss(ssi->device.parent)))
+ goto mode; /* We always need to restore the mode & TX divisor */
+
+ ssi_restore_port_ctx(omap_port);
+
+mode:
+ ssi_restore_divisor(omap_port);
+ ssi_restore_port_mode(omap_port);
+
+ return 0;
+}
+
+static const struct dev_pm_ops omap_ssi_port_pm_ops = {
+ SET_RUNTIME_PM_OPS(omap_ssi_port_runtime_suspend,
+ omap_ssi_port_runtime_resume, NULL)
+};
+
+#define DEV_PM_OPS (&omap_ssi_port_pm_ops)
+#else
+#define DEV_PM_OPS NULL
+#endif
+
+
+#ifdef CONFIG_OF
+static const struct of_device_id omap_ssi_port_of_match[] = {
+ { .compatible = "ti,omap3-ssi-port", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, omap_ssi_port_of_match);
+#else
+#define omap_ssi_port_of_match NULL
+#endif
+
+static struct platform_driver ssi_port_pdriver = {
+ .remove = __exit_p(ssi_port_remove),
+ .driver = {
+ .name = "omap_ssi_port",
+ .owner = THIS_MODULE,
+ .of_match_table = omap_ssi_port_of_match,
+ .pm = DEV_PM_OPS,
+ },
+};
+
+module_platform_driver_probe(ssi_port_pdriver, ssi_port_probe);
+
+MODULE_ALIAS("platform:omap_ssi_port");
+MODULE_AUTHOR("Carlos Chinea <carlos.chinea@nokia.com>");
+MODULE_AUTHOR("Sebastian Reichel <sre@kernel.org>");
+MODULE_DESCRIPTION("Synchronous Serial Interface Port Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hsi/controllers/omap_ssi_regs.h b/drivers/hsi/controllers/omap_ssi_regs.h
new file mode 100644
index 000000000000..08f98dd1d01f
--- /dev/null
+++ b/drivers/hsi/controllers/omap_ssi_regs.h
@@ -0,0 +1,171 @@
+/* Hardware definitions for SSI.
+ *
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Carlos Chinea <carlos.chinea@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef __OMAP_SSI_REGS_H__
+#define __OMAP_SSI_REGS_H__
+
+/*
+ * SSI SYS registers
+ */
+#define SSI_REVISION_REG 0
+# define SSI_REV_MAJOR 0xf0
+# define SSI_REV_MINOR 0xf
+#define SSI_SYSCONFIG_REG 0x10
+# define SSI_AUTOIDLE (1 << 0)
+# define SSI_SOFTRESET (1 << 1)
+# define SSI_SIDLEMODE_FORCE 0
+# define SSI_SIDLEMODE_NO (1 << 3)
+# define SSI_SIDLEMODE_SMART (1 << 4)
+# define SSI_SIDLEMODE_MASK 0x18
+# define SSI_MIDLEMODE_FORCE 0
+# define SSI_MIDLEMODE_NO (1 << 12)
+# define SSI_MIDLEMODE_SMART (1 << 13)
+# define SSI_MIDLEMODE_MASK 0x3000
+#define SSI_SYSSTATUS_REG 0x14
+# define SSI_RESETDONE 1
+#define SSI_MPU_STATUS_REG(port, irq) (0x808 + ((port) * 0x10) + ((irq) * 2))
+#define SSI_MPU_ENABLE_REG(port, irq) (0x80c + ((port) * 0x10) + ((irq) * 8))
+# define SSI_DATAACCEPT(channel) (1 << (channel))
+# define SSI_DATAAVAILABLE(channel) (1 << ((channel) + 8))
+# define SSI_DATAOVERRUN(channel) (1 << ((channel) + 16))
+# define SSI_ERROROCCURED (1 << 24)
+# define SSI_BREAKDETECTED (1 << 25)
+#define SSI_GDD_MPU_IRQ_STATUS_REG 0x0800
+#define SSI_GDD_MPU_IRQ_ENABLE_REG 0x0804
+# define SSI_GDD_LCH(channel) (1 << (channel))
+#define SSI_WAKE_REG(port) (0xc00 + ((port) * 0x10))
+#define SSI_CLEAR_WAKE_REG(port) (0xc04 + ((port) * 0x10))
+#define SSI_SET_WAKE_REG(port) (0xc08 + ((port) * 0x10))
+# define SSI_WAKE(channel) (1 << (channel))
+# define SSI_WAKE_MASK 0xff
+
+/*
+ * SSI SST registers
+ */
+#define SSI_SST_ID_REG 0
+#define SSI_SST_MODE_REG 4
+# define SSI_MODE_VAL_MASK 3
+# define SSI_MODE_SLEEP 0
+# define SSI_MODE_STREAM 1
+# define SSI_MODE_FRAME 2
+# define SSI_MODE_MULTIPOINTS 3
+#define SSI_SST_FRAMESIZE_REG 8
+# define SSI_FRAMESIZE_DEFAULT 31
+#define SSI_SST_TXSTATE_REG 0xc
+# define SSI_TXSTATE_IDLE 0
+#define SSI_SST_BUFSTATE_REG 0x10
+# define SSI_FULL(channel) (1 << (channel))
+#define SSI_SST_DIVISOR_REG 0x18
+# define SSI_MAX_DIVISOR 127
+#define SSI_SST_BREAK_REG 0x20
+#define SSI_SST_CHANNELS_REG 0x24
+# define SSI_CHANNELS_DEFAULT 4
+#define SSI_SST_ARBMODE_REG 0x28
+# define SSI_ARBMODE_ROUNDROBIN 0
+# define SSI_ARBMODE_PRIORITY 1
+#define SSI_SST_BUFFER_CH_REG(channel) (0x80 + ((channel) * 4))
+#define SSI_SST_SWAPBUF_CH_REG(channel) (0xc0 + ((channel) * 4))
+
+/*
+ * SSI SSR registers
+ */
+#define SSI_SSR_ID_REG 0
+#define SSI_SSR_MODE_REG 4
+#define SSI_SSR_FRAMESIZE_REG 8
+#define SSI_SSR_RXSTATE_REG 0xc
+#define SSI_SSR_BUFSTATE_REG 0x10
+# define SSI_NOTEMPTY(channel) (1 << (channel))
+#define SSI_SSR_BREAK_REG 0x1c
+#define SSI_SSR_ERROR_REG 0x20
+#define SSI_SSR_ERRORACK_REG 0x24
+#define SSI_SSR_OVERRUN_REG 0x2c
+#define SSI_SSR_OVERRUNACK_REG 0x30
+#define SSI_SSR_TIMEOUT_REG 0x34
+# define SSI_TIMEOUT_DEFAULT 0
+#define SSI_SSR_CHANNELS_REG 0x28
+#define SSI_SSR_BUFFER_CH_REG(channel) (0x80 + ((channel) * 4))
+#define SSI_SSR_SWAPBUF_CH_REG(channel) (0xc0 + ((channel) * 4))
+
+/*
+ * SSI GDD registers
+ */
+#define SSI_GDD_HW_ID_REG 0
+#define SSI_GDD_PPORT_ID_REG 0x10
+#define SSI_GDD_MPORT_ID_REG 0x14
+#define SSI_GDD_PPORT_SR_REG 0x20
+#define SSI_GDD_MPORT_SR_REG 0x24
+# define SSI_ACTIVE_LCH_NUM_MASK 0xff
+#define SSI_GDD_TEST_REG 0x40
+# define SSI_TEST 1
+#define SSI_GDD_GCR_REG 0x100
+# define SSI_CLK_AUTOGATING_ON (1 << 3)
+# define SSI_FREE (1 << 2)
+# define SSI_SWITCH_OFF (1 << 0)
+#define SSI_GDD_GRST_REG 0x200
+# define SSI_SWRESET 1
+#define SSI_GDD_CSDP_REG(channel) (0x800 + ((channel) * 0x40))
+# define SSI_DST_BURST_EN_MASK 0xc000
+# define SSI_DST_SINGLE_ACCESS0 0
+# define SSI_DST_SINGLE_ACCESS (1 << 14)
+# define SSI_DST_BURST_4x32_BIT (2 << 14)
+# define SSI_DST_BURST_8x32_BIT (3 << 14)
+# define SSI_DST_MASK 0x1e00
+# define SSI_DST_MEMORY_PORT (8 << 9)
+# define SSI_DST_PERIPHERAL_PORT (9 << 9)
+# define SSI_SRC_BURST_EN_MASK 0x180
+# define SSI_SRC_SINGLE_ACCESS0 0
+# define SSI_SRC_SINGLE_ACCESS (1 << 7)
+# define SSI_SRC_BURST_4x32_BIT (2 << 7)
+# define SSI_SRC_BURST_8x32_BIT (3 << 7)
+# define SSI_SRC_MASK 0x3c
+# define SSI_SRC_MEMORY_PORT (8 << 2)
+# define SSI_SRC_PERIPHERAL_PORT (9 << 2)
+# define SSI_DATA_TYPE_MASK 3
+# define SSI_DATA_TYPE_S32 2
+#define SSI_GDD_CCR_REG(channel) (0x802 + ((channel) * 0x40))
+# define SSI_DST_AMODE_MASK (3 << 14)
+# define SSI_DST_AMODE_CONST 0
+# define SSI_DST_AMODE_POSTINC (1 << 12)
+# define SSI_SRC_AMODE_MASK (3 << 12)
+# define SSI_SRC_AMODE_CONST 0
+# define SSI_SRC_AMODE_POSTINC (1 << 12)
+# define SSI_CCR_ENABLE (1 << 7)
+# define SSI_CCR_SYNC_MASK 0x1f
+#define SSI_GDD_CICR_REG(channel) (0x804 + ((channel) * 0x40))
+# define SSI_BLOCK_IE (1 << 5)
+# define SSI_HALF_IE (1 << 2)
+# define SSI_TOUT_IE (1 << 0)
+#define SSI_GDD_CSR_REG(channel) (0x806 + ((channel) * 0x40))
+# define SSI_CSR_SYNC (1 << 6)
+# define SSI_CSR_BLOCK (1 << 5)
+# define SSI_CSR_HALF (1 << 2)
+# define SSI_CSR_TOUR (1 << 0)
+#define SSI_GDD_CSSA_REG(channel) (0x808 + ((channel) * 0x40))
+#define SSI_GDD_CDSA_REG(channel) (0x80c + ((channel) * 0x40))
+#define SSI_GDD_CEN_REG(channel) (0x810 + ((channel) * 0x40))
+#define SSI_GDD_CSAC_REG(channel) (0x818 + ((channel) * 0x40))
+#define SSI_GDD_CDAC_REG(channel) (0x81a + ((channel) * 0x40))
+#define SSI_GDD_CLNK_CTRL_REG(channel) (0x828 + ((channel) * 0x40))
+# define SSI_ENABLE_LNK (1 << 15)
+# define SSI_STOP_LNK (1 << 14)
+# define SSI_NEXT_CH_ID_MASK 0xf
+
+#endif /* __OMAP_SSI_REGS_H__ */
diff --git a/drivers/hsi/hsi.c b/drivers/hsi/hsi.c
index 749f7b5c8179..fe9371271ce2 100644
--- a/drivers/hsi/hsi.c
+++ b/drivers/hsi/hsi.c
@@ -26,6 +26,8 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/notifier.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include "hsi_core.h"
static ssize_t modalias_show(struct device *dev,
@@ -50,7 +52,13 @@ static int hsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
static int hsi_bus_match(struct device *dev, struct device_driver *driver)
{
- return strcmp(dev_name(dev), driver->name) == 0;
+ if (of_driver_match_device(dev, driver))
+ return true;
+
+ if (strcmp(dev_name(dev), driver->name) == 0)
+ return true;
+
+ return false;
}
static struct bus_type hsi_bus_type = {
@@ -62,18 +70,37 @@ static struct bus_type hsi_bus_type = {
static void hsi_client_release(struct device *dev)
{
- kfree(to_hsi_client(dev));
+ struct hsi_client *cl = to_hsi_client(dev);
+
+ kfree(cl->tx_cfg.channels);
+ kfree(cl->rx_cfg.channels);
+ kfree(cl);
}
-static void hsi_new_client(struct hsi_port *port, struct hsi_board_info *info)
+struct hsi_client *hsi_new_client(struct hsi_port *port,
+ struct hsi_board_info *info)
{
struct hsi_client *cl;
+ size_t size;
cl = kzalloc(sizeof(*cl), GFP_KERNEL);
if (!cl)
- return;
+ return NULL;
+
cl->tx_cfg = info->tx_cfg;
+ if (cl->tx_cfg.channels) {
+ size = cl->tx_cfg.num_channels * sizeof(*cl->tx_cfg.channels);
+ cl->tx_cfg.channels = kzalloc(size , GFP_KERNEL);
+ memcpy(cl->tx_cfg.channels, info->tx_cfg.channels, size);
+ }
+
cl->rx_cfg = info->rx_cfg;
+ if (cl->rx_cfg.channels) {
+ size = cl->rx_cfg.num_channels * sizeof(*cl->rx_cfg.channels);
+ cl->rx_cfg.channels = kzalloc(size , GFP_KERNEL);
+ memcpy(cl->rx_cfg.channels, info->rx_cfg.channels, size);
+ }
+
cl->device.bus = &hsi_bus_type;
cl->device.parent = &port->device;
cl->device.release = hsi_client_release;
@@ -85,7 +112,10 @@ static void hsi_new_client(struct hsi_port *port, struct hsi_board_info *info)
pr_err("hsi: failed to register client: %s\n", info->name);
put_device(&cl->device);
}
+
+ return cl;
}
+EXPORT_SYMBOL_GPL(hsi_new_client);
static void hsi_scan_board_info(struct hsi_controller *hsi)
{
@@ -101,12 +131,209 @@ static void hsi_scan_board_info(struct hsi_controller *hsi)
}
}
-static int hsi_remove_client(struct device *dev, void *data __maybe_unused)
+#ifdef CONFIG_OF
+static struct hsi_board_info hsi_char_dev_info = {
+ .name = "hsi_char",
+};
+
+static int hsi_of_property_parse_mode(struct device_node *client, char *name,
+ unsigned int *result)
+{
+ const char *mode;
+ int err;
+
+ err = of_property_read_string(client, name, &mode);
+ if (err < 0)
+ return err;
+
+ if (strcmp(mode, "stream") == 0)
+ *result = HSI_MODE_STREAM;
+ else if (strcmp(mode, "frame") == 0)
+ *result = HSI_MODE_FRAME;
+ else
+ return -EINVAL;
+
+ return 0;
+}
+
+static int hsi_of_property_parse_flow(struct device_node *client, char *name,
+ unsigned int *result)
+{
+ const char *flow;
+ int err;
+
+ err = of_property_read_string(client, name, &flow);
+ if (err < 0)
+ return err;
+
+ if (strcmp(flow, "synchronized") == 0)
+ *result = HSI_FLOW_SYNC;
+ else if (strcmp(flow, "pipeline") == 0)
+ *result = HSI_FLOW_PIPE;
+ else
+ return -EINVAL;
+
+ return 0;
+}
+
+static int hsi_of_property_parse_arb_mode(struct device_node *client,
+ char *name, unsigned int *result)
+{
+ const char *arb_mode;
+ int err;
+
+ err = of_property_read_string(client, name, &arb_mode);
+ if (err < 0)
+ return err;
+
+ if (strcmp(arb_mode, "round-robin") == 0)
+ *result = HSI_ARB_RR;
+ else if (strcmp(arb_mode, "priority") == 0)
+ *result = HSI_ARB_PRIO;
+ else
+ return -EINVAL;
+
+ return 0;
+}
+
+static void hsi_add_client_from_dt(struct hsi_port *port,
+ struct device_node *client)
+{
+ struct hsi_client *cl;
+ struct hsi_channel channel;
+ struct property *prop;
+ char name[32];
+ int length, cells, err, i, max_chan, mode;
+
+ cl = kzalloc(sizeof(*cl), GFP_KERNEL);
+ if (!cl)
+ return;
+
+ err = of_modalias_node(client, name, sizeof(name));
+ if (err)
+ goto err;
+
+ dev_set_name(&cl->device, "%s", name);
+
+ err = hsi_of_property_parse_mode(client, "hsi-mode", &mode);
+ if (err) {
+ err = hsi_of_property_parse_mode(client, "hsi-rx-mode",
+ &cl->rx_cfg.mode);
+ if (err)
+ goto err;
+
+ err = hsi_of_property_parse_mode(client, "hsi-tx-mode",
+ &cl->tx_cfg.mode);
+ if (err)
+ goto err;
+ } else {
+ cl->rx_cfg.mode = mode;
+ cl->tx_cfg.mode = mode;
+ }
+
+ err = of_property_read_u32(client, "hsi-speed-kbps",
+ &cl->tx_cfg.speed);
+ if (err)
+ goto err;
+ cl->rx_cfg.speed = cl->tx_cfg.speed;
+
+ err = hsi_of_property_parse_flow(client, "hsi-flow",
+ &cl->rx_cfg.flow);
+ if (err)
+ goto err;
+
+ err = hsi_of_property_parse_arb_mode(client, "hsi-arb-mode",
+ &cl->rx_cfg.arb_mode);
+ if (err)
+ goto err;
+
+ prop = of_find_property(client, "hsi-channel-ids", &length);
+ if (!prop) {
+ err = -EINVAL;
+ goto err;
+ }
+
+ cells = length / sizeof(u32);
+
+ cl->rx_cfg.num_channels = cells;
+ cl->tx_cfg.num_channels = cells;
+
+ cl->rx_cfg.channels = kzalloc(cells * sizeof(channel), GFP_KERNEL);
+ if (!cl->rx_cfg.channels) {
+ err = -ENOMEM;
+ goto err;
+ }
+
+ cl->tx_cfg.channels = kzalloc(cells * sizeof(channel), GFP_KERNEL);
+ if (!cl->tx_cfg.channels) {
+ err = -ENOMEM;
+ goto err2;
+ }
+
+ max_chan = 0;
+ for (i = 0; i < cells; i++) {
+ err = of_property_read_u32_index(client, "hsi-channel-ids", i,
+ &channel.id);
+ if (err)
+ goto err3;
+
+ err = of_property_read_string_index(client, "hsi-channel-names",
+ i, &channel.name);
+ if (err)
+ channel.name = NULL;
+
+ if (channel.id > max_chan)
+ max_chan = channel.id;
+
+ cl->rx_cfg.channels[i] = channel;
+ cl->tx_cfg.channels[i] = channel;
+ }
+
+ cl->rx_cfg.num_hw_channels = max_chan + 1;
+ cl->tx_cfg.num_hw_channels = max_chan + 1;
+
+ cl->device.bus = &hsi_bus_type;
+ cl->device.parent = &port->device;
+ cl->device.release = hsi_client_release;
+ cl->device.of_node = client;
+
+ if (device_register(&cl->device) < 0) {
+ pr_err("hsi: failed to register client: %s\n", name);
+ put_device(&cl->device);
+ goto err3;
+ }
+
+ return;
+
+err3:
+ kfree(cl->tx_cfg.channels);
+err2:
+ kfree(cl->rx_cfg.channels);
+err:
+ kfree(cl);
+ pr_err("hsi client: missing or incorrect of property: err=%d\n", err);
+}
+
+void hsi_add_clients_from_dt(struct hsi_port *port, struct device_node *clients)
+{
+ struct device_node *child;
+
+ /* register hsi-char device */
+ hsi_new_client(port, &hsi_char_dev_info);
+
+ for_each_available_child_of_node(clients, child)
+ hsi_add_client_from_dt(port, child);
+}
+EXPORT_SYMBOL_GPL(hsi_add_clients_from_dt);
+#endif
+
+int hsi_remove_client(struct device *dev, void *data __maybe_unused)
{
device_unregister(dev);
return 0;
}
+EXPORT_SYMBOL_GPL(hsi_remove_client);
static int hsi_remove_port(struct device *dev, void *data __maybe_unused)
{
@@ -130,6 +357,16 @@ static void hsi_port_release(struct device *dev)
}
/**
+ * hsi_unregister_port - Unregister an HSI port
+ * @port: The HSI port to unregister
+ */
+void hsi_port_unregister_clients(struct hsi_port *port)
+{
+ device_for_each_child(&port->device, NULL, hsi_remove_client);
+}
+EXPORT_SYMBOL_GPL(hsi_port_unregister_clients);
+
+/**
* hsi_unregister_controller - Unregister an HSI controller
* @hsi: The HSI controller to register
*/
@@ -472,7 +709,7 @@ int hsi_unregister_port_event(struct hsi_client *cl)
EXPORT_SYMBOL_GPL(hsi_unregister_port_event);
/**
- * hsi_event -Notifies clients about port events
+ * hsi_event - Notifies clients about port events
* @port: Port where the event occurred
* @event: The event type
*
@@ -492,6 +729,32 @@ int hsi_event(struct hsi_port *port, unsigned long event)
}
EXPORT_SYMBOL_GPL(hsi_event);
+/**
+ * hsi_get_channel_id_by_name - acquire channel id by channel name
+ * @cl: HSI client, which uses the channel
+ * @name: name the channel is known under
+ *
+ * Clients can call this function to get the hsi channel ids similar to
+ * requesting IRQs or GPIOs by name. This function assumes the same
+ * channel configuration is used for RX and TX.
+ *
+ * Returns -errno on error or channel id on success.
+ */
+int hsi_get_channel_id_by_name(struct hsi_client *cl, char *name)
+{
+ int i;
+
+ if (!cl->rx_cfg.channels)
+ return -ENOENT;
+
+ for (i = 0; i < cl->rx_cfg.num_channels; i++)
+ if (!strcmp(cl->rx_cfg.channels[i].name, name))
+ return cl->rx_cfg.channels[i].id;
+
+ return -ENXIO;
+}
+EXPORT_SYMBOL_GPL(hsi_get_channel_id_by_name);
+
static int __init hsi_init(void)
{
return bus_register(&hsi_bus_type);
diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
index f2d7bf90c9fe..2e7801af466e 100644
--- a/drivers/hv/connection.c
+++ b/drivers/hv/connection.c
@@ -55,6 +55,9 @@ static __u32 vmbus_get_next_version(__u32 current_version)
case (VERSION_WIN8):
return VERSION_WIN7;
+ case (VERSION_WIN8_1):
+ return VERSION_WIN8;
+
case (VERSION_WS2008):
default:
return VERSION_INVAL;
@@ -77,7 +80,7 @@ static int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo,
msg->interrupt_page = virt_to_phys(vmbus_connection.int_page);
msg->monitor_page1 = virt_to_phys(vmbus_connection.monitor_pages[0]);
msg->monitor_page2 = virt_to_phys(vmbus_connection.monitor_pages[1]);
- if (version == VERSION_WIN8)
+ if (version == VERSION_WIN8_1)
msg->target_vcpu = hv_context.vp_index[smp_processor_id()];
/*
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index bc196f49ec53..4af0da96c2e2 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -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
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index 6d02e3b06375..d76f0b70c6e0 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -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;
}
diff --git a/drivers/hwmon/emc1403.c b/drivers/hwmon/emc1403.c
index 90ec1173b8a1..01723f04fe45 100644
--- a/drivers/hwmon/emc1403.c
+++ b/drivers/hwmon/emc1403.c
@@ -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);
diff --git a/drivers/hwmon/ltc2945.c b/drivers/hwmon/ltc2945.c
index c104cc32989d..c9cddf5f056b 100644
--- a/drivers/hwmon/ltc2945.c
+++ b/drivers/hwmon/ltc2945.c
@@ -1,4 +1,4 @@
-/*
+ /*
* Driver for Linear Technology LTC2945 I2C Power Monitor
*
* Copyright (c) 2014 Guenter Roeck
@@ -314,8 +314,8 @@ static ssize_t ltc2945_reset_history(struct device *dev,
reg = LTC2945_MAX_ADIN_H;
break;
default:
- BUG();
- break;
+ WARN_ONCE(1, "Bad register: 0x%x\n", reg);
+ return -EINVAL;
}
/* Reset maximum */
ret = regmap_bulk_write(regmap, reg, buf_max, num_regs);
diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
index 8a17f01e8672..e76feb86a1d4 100644
--- a/drivers/hwmon/ntc_thermistor.c
+++ b/drivers/hwmon/ntc_thermistor.c
@@ -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
diff --git a/drivers/hwmon/vexpress.c b/drivers/hwmon/vexpress.c
index d867e6bb2be1..8242b75d96c8 100644
--- a/drivers/hwmon/vexpress.c
+++ b/drivers/hwmon/vexpress.c
@@ -27,15 +27,15 @@
struct vexpress_hwmon_data {
struct device *hwmon_dev;
struct vexpress_config_func *func;
+ const char *name;
};
static ssize_t vexpress_hwmon_name_show(struct device *dev,
struct device_attribute *dev_attr, char *buffer)
{
- const char *compatible = of_get_property(dev->of_node, "compatible",
- NULL);
+ struct vexpress_hwmon_data *data = dev_get_drvdata(dev);
- return sprintf(buffer, "%s\n", compatible);
+ return sprintf(buffer, "%s\n", data->name);
}
static ssize_t vexpress_hwmon_label_show(struct device *dev,
@@ -43,9 +43,6 @@ static ssize_t vexpress_hwmon_label_show(struct device *dev,
{
const char *label = of_get_property(dev->of_node, "label", NULL);
- if (!label)
- return -ENOENT;
-
return snprintf(buffer, PAGE_SIZE, "%s\n", label);
}
@@ -84,6 +81,20 @@ static ssize_t vexpress_hwmon_u64_show(struct device *dev,
to_sensor_dev_attr(dev_attr)->index));
}
+static umode_t vexpress_hwmon_attr_is_visible(struct kobject *kobj,
+ struct attribute *attr, int index)
+{
+ struct device *dev = kobj_to_dev(kobj);
+ struct device_attribute *dev_attr = container_of(attr,
+ struct device_attribute, attr);
+
+ if (dev_attr->show == vexpress_hwmon_label_show &&
+ !of_get_property(dev->of_node, "label", NULL))
+ return 0;
+
+ return attr->mode;
+}
+
static DEVICE_ATTR(name, S_IRUGO, vexpress_hwmon_name_show, NULL);
#define VEXPRESS_HWMON_ATTRS(_name, _label_attr, _input_attr) \
@@ -94,14 +105,27 @@ struct attribute *vexpress_hwmon_attrs_##_name[] = { \
NULL \
}
+struct vexpress_hwmon_type {
+ const char *name;
+ const struct attribute_group **attr_groups;
+};
+
#if !defined(CONFIG_REGULATOR_VEXPRESS)
static DEVICE_ATTR(in1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, vexpress_hwmon_u32_show,
NULL, 1000);
static VEXPRESS_HWMON_ATTRS(volt, in1_label, in1_input);
static struct attribute_group vexpress_hwmon_group_volt = {
+ .is_visible = vexpress_hwmon_attr_is_visible,
.attrs = vexpress_hwmon_attrs_volt,
};
+static struct vexpress_hwmon_type vexpress_hwmon_volt = {
+ .name = "vexpress_volt",
+ .attr_groups = (const struct attribute_group *[]) {
+ &vexpress_hwmon_group_volt,
+ NULL,
+ },
+};
#endif
static DEVICE_ATTR(curr1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
@@ -109,52 +133,84 @@ static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, vexpress_hwmon_u32_show,
NULL, 1000);
static VEXPRESS_HWMON_ATTRS(amp, curr1_label, curr1_input);
static struct attribute_group vexpress_hwmon_group_amp = {
+ .is_visible = vexpress_hwmon_attr_is_visible,
.attrs = vexpress_hwmon_attrs_amp,
};
+static struct vexpress_hwmon_type vexpress_hwmon_amp = {
+ .name = "vexpress_amp",
+ .attr_groups = (const struct attribute_group *[]) {
+ &vexpress_hwmon_group_amp,
+ NULL
+ },
+};
static DEVICE_ATTR(temp1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, vexpress_hwmon_u32_show,
NULL, 1000);
static VEXPRESS_HWMON_ATTRS(temp, temp1_label, temp1_input);
static struct attribute_group vexpress_hwmon_group_temp = {
+ .is_visible = vexpress_hwmon_attr_is_visible,
.attrs = vexpress_hwmon_attrs_temp,
};
+static struct vexpress_hwmon_type vexpress_hwmon_temp = {
+ .name = "vexpress_temp",
+ .attr_groups = (const struct attribute_group *[]) {
+ &vexpress_hwmon_group_temp,
+ NULL
+ },
+};
static DEVICE_ATTR(power1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, vexpress_hwmon_u32_show,
NULL, 1);
static VEXPRESS_HWMON_ATTRS(power, power1_label, power1_input);
static struct attribute_group vexpress_hwmon_group_power = {
+ .is_visible = vexpress_hwmon_attr_is_visible,
.attrs = vexpress_hwmon_attrs_power,
};
+static struct vexpress_hwmon_type vexpress_hwmon_power = {
+ .name = "vexpress_power",
+ .attr_groups = (const struct attribute_group *[]) {
+ &vexpress_hwmon_group_power,
+ NULL
+ },
+};
static DEVICE_ATTR(energy1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
static SENSOR_DEVICE_ATTR(energy1_input, S_IRUGO, vexpress_hwmon_u64_show,
NULL, 1);
static VEXPRESS_HWMON_ATTRS(energy, energy1_label, energy1_input);
static struct attribute_group vexpress_hwmon_group_energy = {
+ .is_visible = vexpress_hwmon_attr_is_visible,
.attrs = vexpress_hwmon_attrs_energy,
};
+static struct vexpress_hwmon_type vexpress_hwmon_energy = {
+ .name = "vexpress_energy",
+ .attr_groups = (const struct attribute_group *[]) {
+ &vexpress_hwmon_group_energy,
+ NULL
+ },
+};
static struct of_device_id vexpress_hwmon_of_match[] = {
#if !defined(CONFIG_REGULATOR_VEXPRESS)
{
.compatible = "arm,vexpress-volt",
- .data = &vexpress_hwmon_group_volt,
+ .data = &vexpress_hwmon_volt,
},
#endif
{
.compatible = "arm,vexpress-amp",
- .data = &vexpress_hwmon_group_amp,
+ .data = &vexpress_hwmon_amp,
}, {
.compatible = "arm,vexpress-temp",
- .data = &vexpress_hwmon_group_temp,
+ .data = &vexpress_hwmon_temp,
}, {
.compatible = "arm,vexpress-power",
- .data = &vexpress_hwmon_group_power,
+ .data = &vexpress_hwmon_power,
}, {
.compatible = "arm,vexpress-energy",
- .data = &vexpress_hwmon_group_energy,
+ .data = &vexpress_hwmon_energy,
},
{}
};
@@ -165,6 +221,7 @@ static int vexpress_hwmon_probe(struct platform_device *pdev)
int err;
const struct of_device_id *match;
struct vexpress_hwmon_data *data;
+ const struct vexpress_hwmon_type *type;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data)
@@ -174,12 +231,14 @@ static int vexpress_hwmon_probe(struct platform_device *pdev)
match = of_match_device(vexpress_hwmon_of_match, &pdev->dev);
if (!match)
return -ENODEV;
+ type = match->data;
+ data->name = type->name;
data->func = vexpress_config_func_get_by_dev(&pdev->dev);
if (!data->func)
return -ENODEV;
- err = sysfs_create_group(&pdev->dev.kobj, match->data);
+ err = sysfs_create_groups(&pdev->dev.kobj, type->attr_groups);
if (err)
goto error;
diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c
index 22e92c3d3d07..3c20e4bd6dd1 100644
--- a/drivers/i2c/busses/i2c-designware-core.c
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -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);
diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c
index 28cbe1b2a2ec..32c85e9ecdae 100644
--- a/drivers/i2c/busses/i2c-nomadik.c
+++ b/drivers/i2c/busses/i2c-nomadik.c
@@ -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;
}
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 1b4cf14f1106..2a5efb5b487c 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -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);
diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c
index d4fa8eba6e9d..06d47aafbb79 100644
--- a/drivers/i2c/busses/i2c-rcar.c
+++ b/drivers/i2c/busses/i2c-rcar.c
@@ -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 = {
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index ae4491062e41..bb3a9964f7e0 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -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;
}
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index a43220c2e3d9..4d140bbbe100 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -750,9 +750,10 @@ void intel_idle_state_table_update(void)
if (package_num + 1 > num_sockets) {
num_sockets = package_num + 1;
- if (num_sockets > 4)
+ if (num_sockets > 4) {
cpuidle_state_table = ivt_cstates_8s;
return;
+ }
}
}
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index d86196cfe4b4..24c28e3f93a3 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -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.
diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c
index 5b1aa027c034..89777ed9abd8 100644
--- a/drivers/iio/adc/at91_adc.c
+++ b/drivers/iio/adc/at91_adc.c
@@ -765,14 +765,17 @@ static int at91_adc_probe_pdata(struct at91_adc_state *st,
if (!pdata)
return -EINVAL;
+ st->caps = (struct at91_adc_caps *)
+ platform_get_device_id(pdev)->driver_data;
+
st->use_external = pdata->use_external_triggers;
st->vref_mv = pdata->vref;
st->channels_mask = pdata->channels_used;
- st->num_channels = pdata->num_channels;
+ st->num_channels = st->caps->num_channels;
st->startup_time = pdata->startup_time;
st->trigger_number = pdata->trigger_number;
st->trigger_list = pdata->trigger_list;
- st->registers = pdata->registers;
+ st->registers = &st->caps->registers;
return 0;
}
@@ -1004,8 +1007,11 @@ static int at91_adc_probe(struct platform_device *pdev)
* the best converted final value between two channels selection
* The formula thus is : Sample and Hold Time = (shtim + 1) / ADCClock
*/
- shtim = round_up((st->sample_hold_time * adc_clk_khz /
- 1000) - 1, 1);
+ if (st->sample_hold_time > 0)
+ shtim = round_up((st->sample_hold_time * adc_clk_khz / 1000)
+ - 1, 1);
+ else
+ shtim = 0;
reg = AT91_ADC_PRESCAL_(prsc) & st->registers->mr_prescal_mask;
reg |= AT91_ADC_STARTUP_(ticks) & st->registers->mr_startup_mask;
@@ -1101,7 +1107,6 @@ static int at91_adc_remove(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_OF
static struct at91_adc_caps at91sam9260_caps = {
.calc_startup_ticks = calc_startup_ticks_9260,
.num_channels = 4,
@@ -1154,11 +1159,27 @@ static const struct of_device_id at91_adc_dt_ids[] = {
{},
};
MODULE_DEVICE_TABLE(of, at91_adc_dt_ids);
-#endif
+
+static const struct platform_device_id at91_adc_ids[] = {
+ {
+ .name = "at91sam9260-adc",
+ .driver_data = (unsigned long)&at91sam9260_caps,
+ }, {
+ .name = "at91sam9g45-adc",
+ .driver_data = (unsigned long)&at91sam9g45_caps,
+ }, {
+ .name = "at91sam9x5-adc",
+ .driver_data = (unsigned long)&at91sam9x5_caps,
+ }, {
+ /* terminator */
+ }
+};
+MODULE_DEVICE_TABLE(platform, at91_adc_ids);
static struct platform_driver at91_adc_driver = {
.probe = at91_adc_probe,
.remove = at91_adc_remove,
+ .id_table = at91_adc_ids,
.driver = {
.name = DRIVER_NAME,
.of_match_table = of_match_ptr(at91_adc_dt_ids),
diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c
index d25b262193a7..affa93f51789 100644
--- a/drivers/iio/adc/exynos_adc.c
+++ b/drivers/iio/adc/exynos_adc.c
@@ -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);
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index cb9f96b446a5..d8ad606c7cd0 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -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)
diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index e108f2a9d827..e472cff6eeae 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -165,7 +165,8 @@ static ssize_t iio_scan_el_show(struct device *dev,
int ret;
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- ret = test_bit(to_iio_dev_attr(attr)->address,
+ /* Ensure ret is 0 or 1. */
+ ret = !!test_bit(to_iio_dev_attr(attr)->address,
indio_dev->buffer->scan_mask);
return sprintf(buf, "%d\n", ret);
@@ -862,7 +863,8 @@ int iio_scan_mask_query(struct iio_dev *indio_dev,
if (!buffer->scan_mask)
return 0;
- return test_bit(bit, buffer->scan_mask);
+ /* Ensure return value is 0 or 1. */
+ return !!test_bit(bit, buffer->scan_mask);
};
EXPORT_SYMBOL_GPL(iio_scan_mask_query);
diff --git a/drivers/iio/light/cm32181.c b/drivers/iio/light/cm32181.c
index 47a6dbac2d0c..d976e6ce60db 100644
--- a/drivers/iio/light/cm32181.c
+++ b/drivers/iio/light/cm32181.c
@@ -221,6 +221,7 @@ static int cm32181_read_raw(struct iio_dev *indio_dev,
*val = cm32181->calibscale;
return IIO_VAL_INT;
case IIO_CHAN_INFO_INT_TIME:
+ *val = 0;
ret = cm32181_read_als_it(cm32181, val2);
return ret;
}
diff --git a/drivers/iio/light/cm36651.c b/drivers/iio/light/cm36651.c
index a45e07492db3..39fc67e82138 100644
--- a/drivers/iio/light/cm36651.c
+++ b/drivers/iio/light/cm36651.c
@@ -652,7 +652,19 @@ static int cm36651_probe(struct i2c_client *client,
cm36651->client = client;
cm36651->ps_client = i2c_new_dummy(client->adapter,
CM36651_I2C_ADDR_PS);
+ if (!cm36651->ps_client) {
+ dev_err(&client->dev, "%s: new i2c device failed\n", __func__);
+ ret = -ENODEV;
+ goto error_disable_reg;
+ }
+
cm36651->ara_client = i2c_new_dummy(client->adapter, CM36651_ARA);
+ if (!cm36651->ara_client) {
+ dev_err(&client->dev, "%s: new i2c device failed\n", __func__);
+ ret = -ENODEV;
+ goto error_i2c_unregister_ps;
+ }
+
mutex_init(&cm36651->lock);
indio_dev->dev.parent = &client->dev;
indio_dev->channels = cm36651_channels;
@@ -664,7 +676,7 @@ static int cm36651_probe(struct i2c_client *client,
ret = cm36651_setup_reg(cm36651);
if (ret) {
dev_err(&client->dev, "%s: register setup failed\n", __func__);
- goto error_disable_reg;
+ goto error_i2c_unregister_ara;
}
ret = request_threaded_irq(client->irq, NULL, cm36651_irq_handler,
@@ -672,7 +684,7 @@ static int cm36651_probe(struct i2c_client *client,
"cm36651", indio_dev);
if (ret) {
dev_err(&client->dev, "%s: request irq failed\n", __func__);
- goto error_disable_reg;
+ goto error_i2c_unregister_ara;
}
ret = iio_device_register(indio_dev);
@@ -685,6 +697,10 @@ static int cm36651_probe(struct i2c_client *client,
error_free_irq:
free_irq(client->irq, indio_dev);
+error_i2c_unregister_ara:
+ i2c_unregister_device(cm36651->ara_client);
+error_i2c_unregister_ps:
+ i2c_unregister_device(cm36651->ps_client);
error_disable_reg:
regulator_disable(cm36651->vled_reg);
return ret;
@@ -698,6 +714,8 @@ static int cm36651_remove(struct i2c_client *client)
iio_device_unregister(indio_dev);
regulator_disable(cm36651->vled_reg);
free_irq(client->irq, indio_dev);
+ i2c_unregister_device(cm36651->ps_client);
+ i2c_unregister_device(cm36651->ara_client);
return 0;
}
diff --git a/drivers/infiniband/hw/cxgb4/Kconfig b/drivers/infiniband/hw/cxgb4/Kconfig
index d4e8983fba53..23f38cf2c5cd 100644
--- a/drivers/infiniband/hw/cxgb4/Kconfig
+++ b/drivers/infiniband/hw/cxgb4/Kconfig
@@ -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>.
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
index 02436d5d0dab..1f863a96a480 100644
--- a/drivers/infiniband/hw/cxgb4/cm.c
+++ b/drivers/infiniband/hw/cxgb4/cm.c
@@ -173,12 +173,15 @@ static void start_ep_timer(struct c4iw_ep *ep)
add_timer(&ep->timer);
}
-static void stop_ep_timer(struct c4iw_ep *ep)
+static int stop_ep_timer(struct c4iw_ep *ep)
{
PDBG("%s ep %p stopping\n", __func__, ep);
del_timer_sync(&ep->timer);
- if (!test_and_set_bit(TIMEOUT, &ep->com.flags))
+ if (!test_and_set_bit(TIMEOUT, &ep->com.flags)) {
c4iw_put_ep(&ep->com);
+ return 0;
+ }
+ return 1;
}
static int c4iw_l2t_send(struct c4iw_rdev *rdev, struct sk_buff *skb,
@@ -584,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)) {
@@ -993,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);
}
@@ -1151,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;
@@ -1161,17 +1168,17 @@ 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);
/*
- * Stop mpa timer. If it expired, then the state has
- * changed and we bail since ep_timeout already aborted
- * the connection.
+ * Stop mpa timer. If it expired, then
+ * we ignore the MPA reply. process_timeout()
+ * will abort the connection.
*/
- stop_ep_timer(ep);
- if (ep->com.state != MPA_REQ_SENT)
- return;
+ if (stop_ep_timer(ep))
+ return 0;
/*
* If we get more than the supported amount of private data
@@ -1193,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. */
@@ -1233,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;
@@ -1335,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;
}
@@ -1353,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;
@@ -1364,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)
@@ -1375,15 +1386,12 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
- if (ep->com.state != MPA_REQ_WAIT)
- return;
-
/*
* If we get more than the supported amount of private data
* then we must fail this connection.
*/
if (ep->mpa_pkt_len + skb->len > sizeof(ep->mpa_pkt)) {
- stop_ep_timer(ep);
+ (void)stop_ep_timer(ep);
abort_connection(ep, skb, GFP_KERNEL);
return;
}
@@ -1413,13 +1421,13 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
if (mpa->revision > mpa_rev) {
printk(KERN_ERR MOD "%s MPA version mismatch. Local = %d,"
" Received = %d\n", __func__, mpa_rev, mpa->revision);
- stop_ep_timer(ep);
+ (void)stop_ep_timer(ep);
abort_connection(ep, skb, GFP_KERNEL);
return;
}
if (memcmp(mpa->key, MPA_KEY_REQ, sizeof(mpa->key))) {
- stop_ep_timer(ep);
+ (void)stop_ep_timer(ep);
abort_connection(ep, skb, GFP_KERNEL);
return;
}
@@ -1430,7 +1438,7 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
* Fail if there's too much private data.
*/
if (plen > MPA_MAX_PRIVATE_DATA) {
- stop_ep_timer(ep);
+ (void)stop_ep_timer(ep);
abort_connection(ep, skb, GFP_KERNEL);
return;
}
@@ -1439,7 +1447,7 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
* If plen does not account for pkt size
*/
if (ep->mpa_pkt_len > (sizeof(*mpa) + plen)) {
- stop_ep_timer(ep);
+ (void)stop_ep_timer(ep);
abort_connection(ep, skb, GFP_KERNEL);
return;
}
@@ -1496,18 +1504,24 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version,
ep->mpa_attr.p2p_type);
- __state_set(&ep->com, MPA_REQ_RCVD);
- stop_ep_timer(ep);
-
- /* drive upcall */
- mutex_lock(&ep->parent_ep->com.mutex);
- if (ep->parent_ep->com.state != DEAD) {
- if (connect_request_upcall(ep))
+ /*
+ * If the endpoint timer already expired, then we ignore
+ * the start request. process_timeout() will abort
+ * the connection.
+ */
+ if (!stop_ep_timer(ep)) {
+ __state_set(&ep->com, MPA_REQ_RCVD);
+
+ /* drive upcall */
+ mutex_lock(&ep->parent_ep->com.mutex);
+ if (ep->parent_ep->com.state != DEAD) {
+ if (connect_request_upcall(ep))
+ abort_connection(ep, skb, GFP_KERNEL);
+ } else {
abort_connection(ep, skb, GFP_KERNEL);
- } else {
- abort_connection(ep, skb, GFP_KERNEL);
+ }
+ mutex_unlock(&ep->parent_ep->com.mutex);
}
- mutex_unlock(&ep->parent_ep->com.mutex);
return;
}
@@ -1519,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)
@@ -1534,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;
@@ -1550,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;
}
@@ -2004,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);
@@ -2265,7 +2287,7 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb)
disconnect = 0;
break;
case MORIBUND:
- stop_ep_timer(ep);
+ (void)stop_ep_timer(ep);
if (ep->com.cm_id && ep->com.qp) {
attrs.next_state = C4IW_QP_STATE_IDLE;
c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
@@ -2325,10 +2347,10 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
case CONNECTING:
break;
case MPA_REQ_WAIT:
- stop_ep_timer(ep);
+ (void)stop_ep_timer(ep);
break;
case MPA_REQ_SENT:
- stop_ep_timer(ep);
+ (void)stop_ep_timer(ep);
if (mpa_rev == 1 || (mpa_rev == 2 && ep->tried_with_mpa_v1))
connect_reply_upcall(ep, -ECONNRESET);
else {
@@ -2433,7 +2455,7 @@ static int close_con_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
__state_set(&ep->com, MORIBUND);
break;
case MORIBUND:
- stop_ep_timer(ep);
+ (void)stop_ep_timer(ep);
if ((ep->com.cm_id) && (ep->com.qp)) {
attrs.next_state = C4IW_QP_STATE_IDLE;
c4iw_modify_qp(ep->com.qp->rhp,
@@ -3028,7 +3050,7 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)
if (!test_and_set_bit(CLOSE_SENT, &ep->com.flags)) {
close = 1;
if (abrupt) {
- stop_ep_timer(ep);
+ (void)stop_ep_timer(ep);
ep->com.state = ABORTING;
} else
ep->com.state = MORIBUND;
@@ -3462,14 +3484,24 @@ static void process_timeout(struct c4iw_ep *ep)
__state_set(&ep->com, ABORTING);
close_complete_upcall(ep, -ETIMEDOUT);
break;
+ case ABORTING:
+ case DEAD:
+
+ /*
+ * These states are expected if the ep timed out at the same
+ * time as another thread was calling stop_ep_timer().
+ * So we silently do nothing for these states.
+ */
+ abort = 0;
+ break;
default:
WARN(1, "%s unexpected state ep %p tid %u state %u\n",
__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);
}
@@ -3483,6 +3515,8 @@ static void process_timedout_eps(void)
tmp = timeout_list.next;
list_del(tmp);
+ tmp->next = NULL;
+ tmp->prev = NULL;
spin_unlock_irq(&timeout_lock);
ep = list_entry(tmp, struct c4iw_ep, entry);
process_timeout(ep);
@@ -3499,6 +3533,7 @@ static void process_work(struct work_struct *work)
unsigned int opcode;
int ret;
+ process_timedout_eps();
while ((skb = skb_dequeue(&rxq))) {
rpl = cplhdr(skb);
dev = *((struct c4iw_dev **) (skb->cb + sizeof(void *)));
@@ -3508,8 +3543,8 @@ static void process_work(struct work_struct *work)
ret = work_handlers[opcode](dev, skb);
if (!ret)
kfree_skb(skb);
+ process_timedout_eps();
}
- process_timedout_eps();
}
static DECLARE_WORK(skb_work, process_work);
@@ -3521,8 +3556,13 @@ static void ep_timeout(unsigned long arg)
spin_lock(&timeout_lock);
if (!test_and_set_bit(TIMEOUT, &ep->com.flags)) {
- list_add_tail(&ep->entry, &timeout_list);
- kickit = 1;
+ /*
+ * Only insert if it is not already on the list.
+ */
+ if (!ep->entry.next) {
+ list_add_tail(&ep->entry, &timeout_list);
+ kickit = 1;
+ }
}
spin_unlock(&timeout_lock);
if (kickit)
diff --git a/drivers/infiniband/hw/cxgb4/cq.c b/drivers/infiniband/hw/cxgb4/cq.c
index ce468e542428..cfaa56ada189 100644
--- a/drivers/infiniband/hw/cxgb4/cq.c
+++ b/drivers/infiniband/hw/cxgb4/cq.c
@@ -235,27 +235,21 @@ int c4iw_flush_sq(struct c4iw_qp *qhp)
struct t4_cq *cq = &chp->cq;
int idx;
struct t4_swsqe *swsqe;
- int error = (qhp->attr.state != C4IW_QP_STATE_CLOSING &&
- qhp->attr.state != C4IW_QP_STATE_IDLE);
if (wq->sq.flush_cidx == -1)
wq->sq.flush_cidx = wq->sq.cidx;
idx = wq->sq.flush_cidx;
BUG_ON(idx >= wq->sq.size);
while (idx != wq->sq.pidx) {
- if (error) {
- swsqe = &wq->sq.sw_sq[idx];
- BUG_ON(swsqe->flushed);
- swsqe->flushed = 1;
- insert_sq_cqe(wq, cq, swsqe);
- if (wq->sq.oldest_read == swsqe) {
- BUG_ON(swsqe->opcode != FW_RI_READ_REQ);
- advance_oldest_read(wq);
- }
- flushed++;
- } else {
- t4_sq_consume(wq);
+ swsqe = &wq->sq.sw_sq[idx];
+ BUG_ON(swsqe->flushed);
+ swsqe->flushed = 1;
+ insert_sq_cqe(wq, cq, swsqe);
+ if (wq->sq.oldest_read == swsqe) {
+ BUG_ON(swsqe->opcode != FW_RI_READ_REQ);
+ advance_oldest_read(wq);
}
+ flushed++;
if (++idx == wq->sq.size)
idx = 0;
}
@@ -678,7 +672,7 @@ skip_cqe:
static int c4iw_poll_cq_one(struct c4iw_cq *chp, struct ib_wc *wc)
{
struct c4iw_qp *qhp = NULL;
- struct t4_cqe cqe = {0, 0}, *rd_cqe;
+ struct t4_cqe uninitialized_var(cqe), *rd_cqe;
struct t4_wq *wq;
u32 credit = 0;
u8 cqe_flushed;
diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c
index 9489a388376c..f4fa50a609e2 100644
--- a/drivers/infiniband/hw/cxgb4/device.c
+++ b/drivers/infiniband/hw/cxgb4/device.c
@@ -682,7 +682,10 @@ static void c4iw_dealloc(struct uld_ctx *ctx)
idr_destroy(&ctx->dev->hwtid_idr);
idr_destroy(&ctx->dev->stid_idr);
idr_destroy(&ctx->dev->atid_idr);
- iounmap(ctx->dev->rdev.oc_mw_kva);
+ if (ctx->dev->rdev.bar2_kva)
+ iounmap(ctx->dev->rdev.bar2_kva);
+ if (ctx->dev->rdev.oc_mw_kva)
+ iounmap(ctx->dev->rdev.oc_mw_kva);
ib_dealloc_device(&ctx->dev->ibdev);
ctx->dev = NULL;
}
@@ -722,11 +725,31 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop)
}
devp->rdev.lldi = *infop;
- devp->rdev.oc_mw_pa = pci_resource_start(devp->rdev.lldi.pdev, 2) +
- (pci_resource_len(devp->rdev.lldi.pdev, 2) -
- roundup_pow_of_two(devp->rdev.lldi.vr->ocq.size));
- devp->rdev.oc_mw_kva = ioremap_wc(devp->rdev.oc_mw_pa,
- devp->rdev.lldi.vr->ocq.size);
+ /*
+ * For T5 devices, we map all of BAR2 with WC.
+ * For T4 devices with onchip qp mem, we map only that part
+ * of BAR2 with WC.
+ */
+ devp->rdev.bar2_pa = pci_resource_start(devp->rdev.lldi.pdev, 2);
+ if (is_t5(devp->rdev.lldi.adapter_type)) {
+ devp->rdev.bar2_kva = ioremap_wc(devp->rdev.bar2_pa,
+ pci_resource_len(devp->rdev.lldi.pdev, 2));
+ if (!devp->rdev.bar2_kva) {
+ pr_err(MOD "Unable to ioremap BAR2\n");
+ return ERR_PTR(-EINVAL);
+ }
+ } else if (ocqp_supported(infop)) {
+ devp->rdev.oc_mw_pa =
+ pci_resource_start(devp->rdev.lldi.pdev, 2) +
+ pci_resource_len(devp->rdev.lldi.pdev, 2) -
+ roundup_pow_of_two(devp->rdev.lldi.vr->ocq.size);
+ devp->rdev.oc_mw_kva = ioremap_wc(devp->rdev.oc_mw_pa,
+ devp->rdev.lldi.vr->ocq.size);
+ if (!devp->rdev.oc_mw_kva) {
+ pr_err(MOD "Unable to ioremap onchip mem\n");
+ return ERR_PTR(-EINVAL);
+ }
+ }
PDBG(KERN_INFO MOD "ocq memory: "
"hw_start 0x%x size %u mw_pa 0x%lx mw_kva %p\n",
@@ -1003,9 +1026,11 @@ static int enable_qp_db(int id, void *p, void *data)
static void resume_rc_qp(struct c4iw_qp *qp)
{
spin_lock(&qp->lock);
- t4_ring_sq_db(&qp->wq, qp->wq.sq.wq_pidx_inc);
+ t4_ring_sq_db(&qp->wq, qp->wq.sq.wq_pidx_inc,
+ is_t5(qp->rhp->rdev.lldi.adapter_type), NULL);
qp->wq.sq.wq_pidx_inc = 0;
- t4_ring_rq_db(&qp->wq, qp->wq.rq.wq_pidx_inc);
+ t4_ring_rq_db(&qp->wq, qp->wq.rq.wq_pidx_inc,
+ is_t5(qp->rhp->rdev.lldi.adapter_type), NULL);
qp->wq.rq.wq_pidx_inc = 0;
spin_unlock(&qp->lock);
}
diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
index e872203c5424..7474b490760a 100644
--- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
+++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
@@ -149,6 +149,8 @@ struct c4iw_rdev {
struct gen_pool *ocqp_pool;
u32 flags;
struct cxgb4_lld_info lldi;
+ unsigned long bar2_pa;
+ void __iomem *bar2_kva;
unsigned long oc_mw_pa;
void __iomem *oc_mw_kva;
struct c4iw_stats stats;
@@ -433,6 +435,7 @@ struct c4iw_qp_attributes {
u8 ecode;
u16 sq_db_inc;
u16 rq_db_inc;
+ u8 send_term;
};
struct c4iw_qp {
diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c
index f9ca072a99ed..ec7a2988a703 100644
--- a/drivers/infiniband/hw/cxgb4/mem.c
+++ b/drivers/infiniband/hw/cxgb4/mem.c
@@ -259,8 +259,12 @@ static int write_tpt_entry(struct c4iw_rdev *rdev, u32 reset_tpt_entry,
if ((!reset_tpt_entry) && (*stag == T4_STAG_UNSET)) {
stag_idx = c4iw_get_resource(&rdev->resource.tpt_table);
- if (!stag_idx)
+ if (!stag_idx) {
+ mutex_lock(&rdev->stats.lock);
+ rdev->stats.stag.fail++;
+ mutex_unlock(&rdev->stats.lock);
return -ENOMEM;
+ }
mutex_lock(&rdev->stats.lock);
rdev->stats.stag.cur += 32;
if (rdev->stats.stag.cur > rdev->stats.stag.max)
diff --git a/drivers/infiniband/hw/cxgb4/provider.c b/drivers/infiniband/hw/cxgb4/provider.c
index 79429256023a..a94a3e12c349 100644
--- a/drivers/infiniband/hw/cxgb4/provider.c
+++ b/drivers/infiniband/hw/cxgb4/provider.c
@@ -328,7 +328,7 @@ static int c4iw_query_device(struct ib_device *ibdev,
props->max_mr = c4iw_num_stags(&dev->rdev);
props->max_pd = T4_MAX_NUM_PD;
props->local_ca_ack_delay = 0;
- props->max_fast_reg_page_list_len = T4_MAX_FR_DEPTH;
+ props->max_fast_reg_page_list_len = t4_max_fr_depth(use_dsgl);
return 0;
}
diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c
index cb76eb5eee1f..086f62f5dc9e 100644
--- a/drivers/infiniband/hw/cxgb4/qp.c
+++ b/drivers/infiniband/hw/cxgb4/qp.c
@@ -212,13 +212,23 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
wq->db = rdev->lldi.db_reg;
wq->gts = rdev->lldi.gts_reg;
- if (user) {
- wq->sq.udb = (u64)pci_resource_start(rdev->lldi.pdev, 2) +
- (wq->sq.qid << rdev->qpshift);
- wq->sq.udb &= PAGE_MASK;
- wq->rq.udb = (u64)pci_resource_start(rdev->lldi.pdev, 2) +
- (wq->rq.qid << rdev->qpshift);
- wq->rq.udb &= PAGE_MASK;
+ if (user || is_t5(rdev->lldi.adapter_type)) {
+ u32 off;
+
+ off = (wq->sq.qid << rdev->qpshift) & PAGE_MASK;
+ if (user) {
+ wq->sq.udb = (u64 __iomem *)(rdev->bar2_pa + off);
+ } else {
+ off += 128 * (wq->sq.qid & rdev->qpmask) + 8;
+ wq->sq.udb = (u64 __iomem *)(rdev->bar2_kva + off);
+ }
+ off = (wq->rq.qid << rdev->qpshift) & PAGE_MASK;
+ if (user) {
+ wq->rq.udb = (u64 __iomem *)(rdev->bar2_pa + off);
+ } else {
+ off += 128 * (wq->rq.qid & rdev->qpmask) + 8;
+ wq->rq.udb = (u64 __iomem *)(rdev->bar2_kva + off);
+ }
}
wq->rdev = rdev;
wq->rq.msn = 1;
@@ -299,9 +309,10 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
if (ret)
goto free_dma;
- PDBG("%s sqid 0x%x rqid 0x%x kdb 0x%p squdb 0x%llx rqudb 0x%llx\n",
+ PDBG("%s sqid 0x%x rqid 0x%x kdb 0x%p squdb 0x%lx rqudb 0x%lx\n",
__func__, wq->sq.qid, wq->rq.qid, wq->db,
- (unsigned long long)wq->sq.udb, (unsigned long long)wq->rq.udb);
+ (__force unsigned long) wq->sq.udb,
+ (__force unsigned long) wq->rq.udb);
return 0;
free_dma:
@@ -425,6 +436,8 @@ static int build_rdma_send(struct t4_sq *sq, union t4_wr *wqe,
default:
return -EINVAL;
}
+ wqe->send.r3 = 0;
+ wqe->send.r4 = 0;
plen = 0;
if (wr->num_sge) {
@@ -555,7 +568,8 @@ static int build_fastreg(struct t4_sq *sq, union t4_wr *wqe,
int pbllen = roundup(wr->wr.fast_reg.page_list_len * sizeof(u64), 32);
int rem;
- if (wr->wr.fast_reg.page_list_len > T4_MAX_FR_DEPTH)
+ if (wr->wr.fast_reg.page_list_len >
+ t4_max_fr_depth(use_dsgl))
return -EINVAL;
wqe->fr.qpbinde_to_dcacpu = 0;
@@ -650,9 +664,10 @@ static int ring_kernel_sq_db(struct c4iw_qp *qhp, u16 inc)
spin_lock_irqsave(&qhp->rhp->lock, flags);
spin_lock(&qhp->lock);
- if (qhp->rhp->db_state == NORMAL) {
- t4_ring_sq_db(&qhp->wq, inc);
- } else {
+ if (qhp->rhp->db_state == NORMAL)
+ t4_ring_sq_db(&qhp->wq, inc,
+ is_t5(qhp->rhp->rdev.lldi.adapter_type), NULL);
+ else {
add_to_fc_list(&qhp->rhp->db_fc_list, &qhp->db_fc_entry);
qhp->wq.sq.wq_pidx_inc += inc;
}
@@ -667,9 +682,10 @@ static int ring_kernel_rq_db(struct c4iw_qp *qhp, u16 inc)
spin_lock_irqsave(&qhp->rhp->lock, flags);
spin_lock(&qhp->lock);
- if (qhp->rhp->db_state == NORMAL) {
- t4_ring_rq_db(&qhp->wq, inc);
- } else {
+ if (qhp->rhp->db_state == NORMAL)
+ t4_ring_rq_db(&qhp->wq, inc,
+ is_t5(qhp->rhp->rdev.lldi.adapter_type), NULL);
+ else {
add_to_fc_list(&qhp->rhp->db_fc_list, &qhp->db_fc_entry);
qhp->wq.rq.wq_pidx_inc += inc;
}
@@ -686,7 +702,7 @@ int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
enum fw_wr_opcodes fw_opcode = 0;
enum fw_ri_wr_flags fw_flags;
struct c4iw_qp *qhp;
- union t4_wr *wqe;
+ union t4_wr *wqe = NULL;
u32 num_wrs;
struct t4_swsqe *swsqe;
unsigned long flag;
@@ -792,7 +808,8 @@ int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
idx += DIV_ROUND_UP(len16*16, T4_EQ_ENTRY_SIZE);
}
if (!qhp->rhp->rdev.status_page->db_off) {
- t4_ring_sq_db(&qhp->wq, idx);
+ t4_ring_sq_db(&qhp->wq, idx,
+ is_t5(qhp->rhp->rdev.lldi.adapter_type), wqe);
spin_unlock_irqrestore(&qhp->lock, flag);
} else {
spin_unlock_irqrestore(&qhp->lock, flag);
@@ -806,7 +823,7 @@ int c4iw_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
{
int err = 0;
struct c4iw_qp *qhp;
- union t4_recv_wr *wqe;
+ union t4_recv_wr *wqe = NULL;
u32 num_wrs;
u8 len16 = 0;
unsigned long flag;
@@ -858,7 +875,8 @@ int c4iw_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
num_wrs--;
}
if (!qhp->rhp->rdev.status_page->db_off) {
- t4_ring_rq_db(&qhp->wq, idx);
+ t4_ring_rq_db(&qhp->wq, idx,
+ is_t5(qhp->rhp->rdev.lldi.adapter_type), wqe);
spin_unlock_irqrestore(&qhp->lock, flag);
} else {
spin_unlock_irqrestore(&qhp->lock, flag);
@@ -1352,6 +1370,7 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
switch (attrs->next_state) {
case C4IW_QP_STATE_CLOSING:
BUG_ON(atomic_read(&qhp->ep->com.kref.refcount) < 2);
+ t4_set_wq_in_error(&qhp->wq);
set_state(qhp, C4IW_QP_STATE_CLOSING);
ep = qhp->ep;
if (!internal) {
@@ -1359,30 +1378,30 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
disconnect = 1;
c4iw_get_ep(&qhp->ep->com);
}
- t4_set_wq_in_error(&qhp->wq);
ret = rdma_fini(rhp, qhp, ep);
if (ret)
goto err;
break;
case C4IW_QP_STATE_TERMINATE:
+ t4_set_wq_in_error(&qhp->wq);
set_state(qhp, C4IW_QP_STATE_TERMINATE);
qhp->attr.layer_etype = attrs->layer_etype;
qhp->attr.ecode = attrs->ecode;
- t4_set_wq_in_error(&qhp->wq);
ep = qhp->ep;
- disconnect = 1;
- 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;
}
- c4iw_get_ep(&qhp->ep->com);
break;
case C4IW_QP_STATE_ERROR:
- set_state(qhp, C4IW_QP_STATE_ERROR);
t4_set_wq_in_error(&qhp->wq);
+ set_state(qhp, C4IW_QP_STATE_ERROR);
if (!internal) {
abort = 1;
disconnect = 1;
@@ -1677,11 +1696,11 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
mm2->len = PAGE_ALIGN(qhp->wq.rq.memsize);
insert_mmap(ucontext, mm2);
mm3->key = uresp.sq_db_gts_key;
- mm3->addr = qhp->wq.sq.udb;
+ mm3->addr = (__force unsigned long) qhp->wq.sq.udb;
mm3->len = PAGE_SIZE;
insert_mmap(ucontext, mm3);
mm4->key = uresp.rq_db_gts_key;
- mm4->addr = qhp->wq.rq.udb;
+ mm4->addr = (__force unsigned long) qhp->wq.rq.udb;
mm4->len = PAGE_SIZE;
insert_mmap(ucontext, mm4);
if (mm5) {
@@ -1758,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);
}
diff --git a/drivers/infiniband/hw/cxgb4/resource.c b/drivers/infiniband/hw/cxgb4/resource.c
index cdef4d7fb6d8..67df71a7012e 100644
--- a/drivers/infiniband/hw/cxgb4/resource.c
+++ b/drivers/infiniband/hw/cxgb4/resource.c
@@ -179,8 +179,12 @@ u32 c4iw_get_qpid(struct c4iw_rdev *rdev, struct c4iw_dev_ucontext *uctx)
kfree(entry);
} else {
qid = c4iw_get_resource(&rdev->resource.qid_table);
- if (!qid)
+ if (!qid) {
+ mutex_lock(&rdev->stats.lock);
+ rdev->stats.qid.fail++;
+ mutex_unlock(&rdev->stats.lock);
goto out;
+ }
mutex_lock(&rdev->stats.lock);
rdev->stats.qid.cur += rdev->qpmask + 1;
mutex_unlock(&rdev->stats.lock);
@@ -322,8 +326,8 @@ u32 c4iw_rqtpool_alloc(struct c4iw_rdev *rdev, int size)
unsigned long addr = gen_pool_alloc(rdev->rqt_pool, size << 6);
PDBG("%s addr 0x%x size %d\n", __func__, (u32)addr, size << 6);
if (!addr)
- printk_ratelimited(KERN_WARNING MOD "%s: Out of RQT memory\n",
- pci_name(rdev->lldi.pdev));
+ pr_warn_ratelimited(MOD "%s: Out of RQT memory\n",
+ pci_name(rdev->lldi.pdev));
mutex_lock(&rdev->stats.lock);
if (addr) {
rdev->stats.rqt.cur += roundup(size << 6, 1 << MIN_RQT_SHIFT);
diff --git a/drivers/infiniband/hw/cxgb4/t4.h b/drivers/infiniband/hw/cxgb4/t4.h
index eeca8b1e6376..2178f3198410 100644
--- a/drivers/infiniband/hw/cxgb4/t4.h
+++ b/drivers/infiniband/hw/cxgb4/t4.h
@@ -84,7 +84,14 @@ struct t4_status_page {
sizeof(struct fw_ri_isgl)) / sizeof(struct fw_ri_sge))
#define T4_MAX_FR_IMMD ((T4_SQ_NUM_BYTES - sizeof(struct fw_ri_fr_nsmr_wr) - \
sizeof(struct fw_ri_immd)) & ~31UL)
-#define T4_MAX_FR_DEPTH (1024 / sizeof(u64))
+#define T4_MAX_FR_IMMD_DEPTH (T4_MAX_FR_IMMD / sizeof(u64))
+#define T4_MAX_FR_DSGL 1024
+#define T4_MAX_FR_DSGL_DEPTH (T4_MAX_FR_DSGL / sizeof(u64))
+
+static inline int t4_max_fr_depth(int use_dsgl)
+{
+ return use_dsgl ? T4_MAX_FR_DSGL_DEPTH : T4_MAX_FR_IMMD_DEPTH;
+}
#define T4_RQ_NUM_SLOTS 2
#define T4_RQ_NUM_BYTES (T4_EQ_ENTRY_SIZE * T4_RQ_NUM_SLOTS)
@@ -292,7 +299,7 @@ struct t4_sq {
unsigned long phys_addr;
struct t4_swsqe *sw_sq;
struct t4_swsqe *oldest_read;
- u64 udb;
+ u64 __iomem *udb;
size_t memsize;
u32 qid;
u16 in_use;
@@ -314,7 +321,7 @@ struct t4_rq {
dma_addr_t dma_addr;
DEFINE_DMA_UNMAP_ADDR(mapping);
struct t4_swrqe *sw_rq;
- u64 udb;
+ u64 __iomem *udb;
size_t memsize;
u32 qid;
u32 msn;
@@ -435,15 +442,67 @@ static inline u16 t4_sq_wq_size(struct t4_wq *wq)
return wq->sq.size * T4_SQ_NUM_SLOTS;
}
-static inline void t4_ring_sq_db(struct t4_wq *wq, u16 inc)
+/* This function copies 64 byte coalesced work request to memory
+ * mapped BAR2 space. For coalesced WRs, the SGE fetches data
+ * from the FIFO instead of from Host.
+ */
+static inline void pio_copy(u64 __iomem *dst, u64 *src)
+{
+ int count = 8;
+
+ while (count) {
+ writeq(*src, dst);
+ src++;
+ dst++;
+ count--;
+ }
+}
+
+static inline void t4_ring_sq_db(struct t4_wq *wq, u16 inc, u8 t5,
+ union t4_wr *wqe)
{
+
+ /* Flush host queue memory writes. */
wmb();
+ if (t5) {
+ if (inc == 1 && wqe) {
+ PDBG("%s: WC wq->sq.pidx = %d\n",
+ __func__, wq->sq.pidx);
+ pio_copy(wq->sq.udb + 7, (void *)wqe);
+ } else {
+ PDBG("%s: DB wq->sq.pidx = %d\n",
+ __func__, wq->sq.pidx);
+ writel(PIDX_T5(inc), wq->sq.udb);
+ }
+
+ /* Flush user doorbell area writes. */
+ wmb();
+ return;
+ }
writel(QID(wq->sq.qid) | PIDX(inc), wq->db);
}
-static inline void t4_ring_rq_db(struct t4_wq *wq, u16 inc)
+static inline void t4_ring_rq_db(struct t4_wq *wq, u16 inc, u8 t5,
+ union t4_recv_wr *wqe)
{
+
+ /* Flush host queue memory writes. */
wmb();
+ if (t5) {
+ if (inc == 1 && wqe) {
+ PDBG("%s: WC wq->rq.pidx = %d\n",
+ __func__, wq->rq.pidx);
+ pio_copy(wq->rq.udb + 7, (void *)wqe);
+ } else {
+ PDBG("%s: DB wq->rq.pidx = %d\n",
+ __func__, wq->rq.pidx);
+ writel(PIDX_T5(inc), wq->rq.udb);
+ }
+
+ /* Flush user doorbell area writes. */
+ wmb();
+ return;
+ }
writel(QID(wq->rq.qid) | PIDX(inc), wq->db);
}
@@ -568,6 +627,9 @@ static inline int t4_next_hw_cqe(struct t4_cq *cq, struct t4_cqe **cqe)
printk(KERN_ERR MOD "cq overflow cqid %u\n", cq->cqid);
BUG_ON(1);
} else if (t4_valid_cqe(cq, &cq->queue[cq->cidx])) {
+
+ /* Ensure CQE is flushed to memory */
+ rmb();
*cqe = &cq->queue[cq->cidx];
ret = 0;
} else
diff --git a/drivers/infiniband/hw/cxgb4/t4fw_ri_api.h b/drivers/infiniband/hw/cxgb4/t4fw_ri_api.h
index dc193c292671..6121ca08fe58 100644
--- a/drivers/infiniband/hw/cxgb4/t4fw_ri_api.h
+++ b/drivers/infiniband/hw/cxgb4/t4fw_ri_api.h
@@ -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_ */
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index 1b6dbe156a37..199c7896f081 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -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);
}
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h
index f589522fddfd..66b0b7dbd9f4 100644
--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
+++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
@@ -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 {
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 41308af4163c..dc57482ae7af 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -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;
}
}
}
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index fa6dc870adae..364d4b6937f5 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -282,6 +282,8 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
props->sig_guard_cap = IB_GUARD_T10DIF_CRC |
IB_GUARD_T10DIF_CSUM;
}
+ if (flags & MLX5_DEV_CAP_FLAG_BLOCK_MCAST)
+ props->device_cap_flags |= IB_DEVICE_BLOCK_MULTICAST_LOOPBACK;
props->vendor_id = be32_to_cpup((__be32 *)(out_mad->data + 36)) &
0xffffff;
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c
index ae788d27b93f..dc930ed21eca 100644
--- a/drivers/infiniband/hw/mlx5/qp.c
+++ b/drivers/infiniband/hw/mlx5/qp.c
@@ -807,6 +807,15 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd,
spin_lock_init(&qp->sq.lock);
spin_lock_init(&qp->rq.lock);
+ if (init_attr->create_flags & IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK) {
+ if (!(dev->mdev.caps.flags & MLX5_DEV_CAP_FLAG_BLOCK_MCAST)) {
+ mlx5_ib_dbg(dev, "block multicast loopback isn't supported\n");
+ return -EINVAL;
+ } else {
+ qp->flags |= MLX5_IB_QP_BLOCK_MULTICAST_LOOPBACK;
+ }
+ }
+
if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR)
qp->sq_signal_bits = MLX5_WQE_CTRL_CQ_UPDATE;
@@ -878,6 +887,9 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd,
if (qp->wq_sig)
in->ctx.flags_pd |= cpu_to_be32(MLX5_QP_ENABLE_SIG);
+ if (qp->flags & MLX5_IB_QP_BLOCK_MULTICAST_LOOPBACK)
+ in->ctx.flags_pd |= cpu_to_be32(MLX5_QP_BLOCK_MCAST);
+
if (qp->scat_cqe && is_connected(init_attr->qp_type)) {
int rcqe_sz;
int scqe_sz;
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
index 87897b95666d..ded76c101dde 100644
--- a/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/drivers/infiniband/hw/mthca/mthca_main.c
@@ -858,13 +858,9 @@ static int mthca_enable_msi_x(struct mthca_dev *mdev)
entries[1].entry = 1;
entries[2].entry = 2;
- err = pci_enable_msix(mdev->pdev, entries, ARRAY_SIZE(entries));
- if (err) {
- if (err > 0)
- mthca_info(mdev, "Only %d MSI-X vectors available, "
- "not using MSI-X\n", err);
+ err = pci_enable_msix_exact(mdev->pdev, entries, ARRAY_SIZE(entries));
+ if (err)
return err;
- }
mdev->eq_table.eq[MTHCA_EQ_COMP ].msi_x_vector = entries[0].vector;
mdev->eq_table.eq[MTHCA_EQ_ASYNC].msi_x_vector = entries[1].vector;
diff --git a/drivers/infiniband/hw/qib/qib_pcie.c b/drivers/infiniband/hw/qib/qib_pcie.c
index c8d9c4ab142b..61a0046efb76 100644
--- a/drivers/infiniband/hw/qib/qib_pcie.c
+++ b/drivers/infiniband/hw/qib/qib_pcie.c
@@ -197,46 +197,47 @@ static void qib_msix_setup(struct qib_devdata *dd, int pos, u32 *msixcnt,
struct qib_msix_entry *qib_msix_entry)
{
int ret;
- u32 tabsize = 0;
- u16 msix_flags;
+ int nvec = *msixcnt;
struct msix_entry *msix_entry;
int i;
+ ret = pci_msix_vec_count(dd->pcidev);
+ if (ret < 0)
+ goto do_intx;
+
+ nvec = min(nvec, ret);
+
/* We can't pass qib_msix_entry array to qib_msix_setup
* so use a dummy msix_entry array and copy the allocated
* irq back to the qib_msix_entry array. */
- msix_entry = kmalloc(*msixcnt * sizeof(*msix_entry), GFP_KERNEL);
- if (!msix_entry) {
- ret = -ENOMEM;
+ msix_entry = kmalloc(nvec * sizeof(*msix_entry), GFP_KERNEL);
+ if (!msix_entry)
goto do_intx;
- }
- for (i = 0; i < *msixcnt; i++)
+
+ for (i = 0; i < nvec; i++)
msix_entry[i] = qib_msix_entry[i].msix;
- pci_read_config_word(dd->pcidev, pos + PCI_MSIX_FLAGS, &msix_flags);
- tabsize = 1 + (msix_flags & PCI_MSIX_FLAGS_QSIZE);
- if (tabsize > *msixcnt)
- tabsize = *msixcnt;
- ret = pci_enable_msix(dd->pcidev, msix_entry, tabsize);
- if (ret > 0) {
- tabsize = ret;
- ret = pci_enable_msix(dd->pcidev, msix_entry, tabsize);
- }
-do_intx:
- if (ret) {
- qib_dev_err(dd,
- "pci_enable_msix %d vectors failed: %d, falling back to INTx\n",
- tabsize, ret);
- tabsize = 0;
- }
- for (i = 0; i < tabsize; i++)
+ ret = pci_enable_msix_range(dd->pcidev, msix_entry, 1, nvec);
+ if (ret < 0)
+ goto free_msix_entry;
+ else
+ nvec = ret;
+
+ for (i = 0; i < nvec; i++)
qib_msix_entry[i].msix = msix_entry[i];
+
kfree(msix_entry);
- *msixcnt = tabsize;
+ *msixcnt = nvec;
+ return;
- if (ret)
- qib_enable_intx(dd->pcidev);
+free_msix_entry:
+ kfree(msix_entry);
+do_intx:
+ qib_dev_err(dd, "pci_enable_msix_range %d vectors failed: %d, "
+ "falling back to INTx\n", nvec, ret);
+ *msixcnt = 0;
+ qib_enable_intx(dd->pcidev);
}
/**
diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c
index c98fdb185931..a1710465faaf 100644
--- a/drivers/infiniband/ulp/isert/ib_isert.c
+++ b/drivers/infiniband/ulp/isert/ib_isert.c
@@ -28,6 +28,7 @@
#include <target/target_core_base.h>
#include <target/target_core_fabric.h>
#include <target/iscsi/iscsi_transport.h>
+#include <linux/semaphore.h>
#include "isert_proto.h"
#include "ib_isert.h"
@@ -561,7 +562,15 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
struct isert_device *device;
struct ib_device *ib_dev = cma_id->device;
int ret = 0;
- u8 pi_support = np->tpg_np->tpg->tpg_attrib.t10_pi;
+ u8 pi_support;
+
+ spin_lock_bh(&np->np_thread_lock);
+ if (!np->enabled) {
+ spin_unlock_bh(&np->np_thread_lock);
+ pr_debug("iscsi_np is not enabled, reject connect request\n");
+ return rdma_reject(cma_id, NULL, 0);
+ }
+ spin_unlock_bh(&np->np_thread_lock);
pr_debug("Entering isert_connect_request cma_id: %p, context: %p\n",
cma_id, cma_id->context);
@@ -652,6 +661,7 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
goto out_mr;
}
+ pi_support = np->tpg_np->tpg->tpg_attrib.t10_pi;
if (pi_support && !device->pi_capable) {
pr_err("Protection information requested but not supported\n");
ret = -EINVAL;
@@ -663,11 +673,11 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
goto out_conn_dev;
mutex_lock(&isert_np->np_accept_mutex);
- list_add_tail(&isert_np->np_accept_list, &isert_conn->conn_accept_node);
+ list_add_tail(&isert_conn->conn_accept_node, &isert_np->np_accept_list);
mutex_unlock(&isert_np->np_accept_mutex);
- pr_debug("isert_connect_request() waking up np_accept_wq: %p\n", np);
- wake_up(&isert_np->np_accept_wq);
+ pr_debug("isert_connect_request() up np_sem np: %p\n", np);
+ up(&isert_np->np_sem);
return 0;
out_conn_dev:
@@ -2999,7 +3009,7 @@ isert_setup_np(struct iscsi_np *np,
pr_err("Unable to allocate struct isert_np\n");
return -ENOMEM;
}
- init_waitqueue_head(&isert_np->np_accept_wq);
+ sema_init(&isert_np->np_sem, 0);
mutex_init(&isert_np->np_accept_mutex);
INIT_LIST_HEAD(&isert_np->np_accept_list);
init_completion(&isert_np->np_login_comp);
@@ -3048,18 +3058,6 @@ out:
}
static int
-isert_check_accept_queue(struct isert_np *isert_np)
-{
- int empty;
-
- mutex_lock(&isert_np->np_accept_mutex);
- empty = list_empty(&isert_np->np_accept_list);
- mutex_unlock(&isert_np->np_accept_mutex);
-
- return empty;
-}
-
-static int
isert_rdma_accept(struct isert_conn *isert_conn)
{
struct rdma_cm_id *cm_id = isert_conn->conn_cm_id;
@@ -3151,16 +3149,14 @@ isert_accept_np(struct iscsi_np *np, struct iscsi_conn *conn)
int max_accept = 0, ret;
accept_wait:
- ret = wait_event_interruptible(isert_np->np_accept_wq,
- !isert_check_accept_queue(isert_np) ||
- np->np_thread_state == ISCSI_NP_THREAD_RESET);
+ ret = down_interruptible(&isert_np->np_sem);
if (max_accept > 5)
return -ENODEV;
spin_lock_bh(&np->np_thread_lock);
if (np->np_thread_state == ISCSI_NP_THREAD_RESET) {
spin_unlock_bh(&np->np_thread_lock);
- pr_err("ISCSI_NP_THREAD_RESET for isert_accept_np\n");
+ pr_debug("ISCSI_NP_THREAD_RESET for isert_accept_np\n");
return -ENODEV;
}
spin_unlock_bh(&np->np_thread_lock);
diff --git a/drivers/infiniband/ulp/isert/ib_isert.h b/drivers/infiniband/ulp/isert/ib_isert.h
index 4c072ae34c01..da6612e68000 100644
--- a/drivers/infiniband/ulp/isert/ib_isert.h
+++ b/drivers/infiniband/ulp/isert/ib_isert.h
@@ -182,7 +182,7 @@ struct isert_device {
};
struct isert_np {
- wait_queue_head_t np_accept_wq;
+ struct semaphore np_sem;
struct rdma_cm_id *np_cm_id;
struct mutex np_accept_mutex;
struct list_head np_accept_list;
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 76842d7dc2e3..ffc7ad3a2c88 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -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
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index 2626773ff29b..2dd1d0dd4f7d 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -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,
+ },
{ }
};
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c
index d8241ba0afa0..a15063bea700 100644
--- a/drivers/input/keyboard/pxa27x_keypad.c
+++ b/drivers/input/keyboard/pxa27x_keypad.c
@@ -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);
diff --git a/drivers/input/keyboard/tca8418_keypad.c b/drivers/input/keyboard/tca8418_keypad.c
index 55c15304ddbc..4e491c1762cf 100644
--- a/drivers/input/keyboard/tca8418_keypad.c
+++ b/drivers/input/keyboard/tca8418_keypad.c
@@ -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 = {
diff --git a/drivers/input/misc/bma150.c b/drivers/input/misc/bma150.c
index 52d3a9b28f0b..b36831c828d3 100644
--- a/drivers/input/misc/bma150.c
+++ b/drivers/input/misc/bma150.c
@@ -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 },
{ }
diff --git a/drivers/input/misc/da9055_onkey.c b/drivers/input/misc/da9055_onkey.c
index 4b11ede34950..4765799fef74 100644
--- a/drivers/input/misc/da9055_onkey.c
+++ b/drivers/input/misc/da9055_onkey.c
@@ -109,7 +109,6 @@ static int da9055_onkey_probe(struct platform_device *pdev)
INIT_DELAYED_WORK(&onkey->work, da9055_onkey_work);
- irq = regmap_irq_get_virq(da9055->irq_data, irq);
err = request_threaded_irq(irq, NULL, da9055_onkey_irq,
IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
"ONKEY", onkey);
diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c
index 08ead2aaede5..20c80f543d5e 100644
--- a/drivers/input/misc/soc_button_array.c
+++ b/drivers/input/misc/soc_button_array.c
@@ -169,6 +169,7 @@ static int soc_button_pnp_probe(struct pnp_dev *pdev,
soc_button_remove(pdev);
return error;
}
+ continue;
}
priv->children[i] = pd;
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index effa9c5f2c5c..6b8441f7bc32 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -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
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index ef1cf52f8bb9..b96e978a37b7 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -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;
@@ -1331,6 +1336,22 @@ static int elantech_reconnect(struct psmouse *psmouse)
}
/*
+ * 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.
*/
static int elantech_set_properties(struct elantech_data *etd)
@@ -1353,6 +1374,7 @@ static int elantech_set_properties(struct elantech_data *etd)
case 6:
case 7:
case 8:
+ case 9:
etd->hw_version = 4;
break;
default:
@@ -1389,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;
}
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h
index 036a04abaef7..9e0e2a1f340d 100644
--- a/drivers/input/mouse/elantech.h
+++ b/drivers/input/mouse/elantech.h
@@ -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;
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index d8d49d10f9bb..c5ec703c727e 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -117,6 +117,81 @@ 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",
+ "LEN0018",
+ "LEN0019",
+ "LEN0023",
+ "LEN002A",
+ "LEN002B",
+ "LEN002C",
+ "LEN002D",
+ "LEN002E",
+ "LEN0033", /* Helix */
+ "LEN0034", /* T431s, L440, L540, T540, W540, X1 Carbon 2nd */
+ "LEN0035", /* X240 */
+ "LEN0036", /* T440 */
+ "LEN0037",
+ "LEN0038",
+ "LEN0041",
+ "LEN0042", /* Yoga */
+ "LEN0045",
+ "LEN0046",
+ "LEN0047",
+ "LEN0048",
+ "LEN0049",
+ "LEN2000",
+ "LEN2001", /* Edge E431 */
+ "LEN2002",
+ "LEN2003",
+ "LEN2004", /* L440 */
+ "LEN2005",
+ "LEN2006",
+ "LEN2007",
+ "LEN2008",
+ "LEN2009",
+ "LEN200A",
+ "LEN200B",
+ 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
@@ -266,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;
@@ -1255,8 +1330,10 @@ static void set_abs_position_params(struct input_dev *dev,
input_abs_set_res(dev, y_code, priv->y_res);
}
-static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
+static void set_input_params(struct psmouse *psmouse,
+ struct synaptics_data *priv)
{
+ struct input_dev *dev = psmouse->dev;
int i;
/* Things that apply to both modes */
@@ -1325,6 +1402,8 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
__set_bit(INPUT_PROP_BUTTONPAD, dev->propbit);
+ 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);
@@ -1496,54 +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 T440s */
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T440"),
- },
- .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},
- },
-#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)
@@ -1593,7 +1628,7 @@ static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode)
priv->capabilities, priv->ext_cap, priv->ext_cap_0c,
priv->board_id, priv->firmware_id);
- set_input_params(psmouse->dev, priv);
+ set_input_params(psmouse, priv);
/*
* Encode touchpad model so that it can be used to set
diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c
index 762b08432de0..8b748d99b934 100644
--- a/drivers/input/serio/ambakmi.c
+++ b/drivers/input/serio/ambakmi.c
@@ -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);
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index 0ec9abbe31fe..381b20d4c561 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -702,6 +702,17 @@ static int i8042_pnp_aux_irq;
static char i8042_pnp_kbd_name[32];
static char i8042_pnp_aux_name[32];
+static void i8042_pnp_id_to_string(struct pnp_id *id, char *dst, int dst_size)
+{
+ strlcpy(dst, "PNP:", dst_size);
+
+ while (id) {
+ strlcat(dst, " ", dst_size);
+ strlcat(dst, id->id, dst_size);
+ id = id->next;
+ }
+}
+
static int i8042_pnp_kbd_probe(struct pnp_dev *dev, const struct pnp_device_id *did)
{
if (pnp_port_valid(dev, 0) && pnp_port_len(dev, 0) == 1)
@@ -718,6 +729,8 @@ static int i8042_pnp_kbd_probe(struct pnp_dev *dev, const struct pnp_device_id *
strlcat(i8042_pnp_kbd_name, ":", sizeof(i8042_pnp_kbd_name));
strlcat(i8042_pnp_kbd_name, pnp_dev_name(dev), sizeof(i8042_pnp_kbd_name));
}
+ i8042_pnp_id_to_string(dev->id, i8042_kbd_firmware_id,
+ sizeof(i8042_kbd_firmware_id));
/* Keyboard ports are always supposed to be wakeup-enabled */
device_set_wakeup_enable(&dev->dev, true);
@@ -742,6 +755,8 @@ static int i8042_pnp_aux_probe(struct pnp_dev *dev, const struct pnp_device_id *
strlcat(i8042_pnp_aux_name, ":", sizeof(i8042_pnp_aux_name));
strlcat(i8042_pnp_aux_name, pnp_dev_name(dev), sizeof(i8042_pnp_aux_name));
}
+ i8042_pnp_id_to_string(dev->id, i8042_aux_firmware_id,
+ sizeof(i8042_aux_firmware_id));
i8042_pnp_aux_devices++;
return 0;
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index 020053fa5aaa..3807c3e971cc 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -87,6 +87,8 @@ MODULE_PARM_DESC(debug, "Turn i8042 debugging mode on and off");
#endif
static bool i8042_bypass_aux_irq_test;
+static char i8042_kbd_firmware_id[128];
+static char i8042_aux_firmware_id[128];
#include "i8042.h"
@@ -1218,6 +1220,8 @@ static int __init i8042_create_kbd_port(void)
serio->dev.parent = &i8042_platform_device->dev;
strlcpy(serio->name, "i8042 KBD port", sizeof(serio->name));
strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys));
+ strlcpy(serio->firmware_id, i8042_kbd_firmware_id,
+ sizeof(serio->firmware_id));
port->serio = serio;
port->irq = I8042_KBD_IRQ;
@@ -1244,6 +1248,8 @@ static int __init i8042_create_aux_port(int idx)
if (idx < 0) {
strlcpy(serio->name, "i8042 AUX port", sizeof(serio->name));
strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys));
+ strlcpy(serio->firmware_id, i8042_aux_firmware_id,
+ sizeof(serio->firmware_id));
serio->close = i8042_port_close;
} else {
snprintf(serio->name, sizeof(serio->name), "i8042 AUX%d port", idx);
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 8f4c4ab04bc2..b29134de983b 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -451,6 +451,13 @@ static ssize_t serio_set_bind_mode(struct device *dev, struct device_attribute *
return retval;
}
+static ssize_t firmware_id_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct serio *serio = to_serio_port(dev);
+
+ return sprintf(buf, "%s\n", serio->firmware_id);
+}
+
static DEVICE_ATTR_RO(type);
static DEVICE_ATTR_RO(proto);
static DEVICE_ATTR_RO(id);
@@ -473,12 +480,14 @@ static DEVICE_ATTR_RO(modalias);
static DEVICE_ATTR_WO(drvctl);
static DEVICE_ATTR(description, S_IRUGO, serio_show_description, NULL);
static DEVICE_ATTR(bind_mode, S_IWUSR | S_IRUGO, serio_show_bind_mode, serio_set_bind_mode);
+static DEVICE_ATTR_RO(firmware_id);
static struct attribute *serio_device_attrs[] = {
&dev_attr_modalias.attr,
&dev_attr_description.attr,
&dev_attr_drvctl.attr,
&dev_attr_bind_mode.attr,
+ &dev_attr_firmware_id.attr,
NULL
};
@@ -921,9 +930,14 @@ static int serio_uevent(struct device *dev, struct kobj_uevent_env *env)
SERIO_ADD_UEVENT_VAR("SERIO_PROTO=%02x", serio->id.proto);
SERIO_ADD_UEVENT_VAR("SERIO_ID=%02x", serio->id.id);
SERIO_ADD_UEVENT_VAR("SERIO_EXTRA=%02x", serio->id.extra);
+
SERIO_ADD_UEVENT_VAR("MODALIAS=serio:ty%02Xpr%02Xid%02Xex%02X",
serio->id.type, serio->id.proto, serio->id.id, serio->id.extra);
+ if (serio->firmware_id[0])
+ SERIO_ADD_UEVENT_VAR("SERIO_FIRMWARE_ID=%s",
+ serio->firmware_id);
+
return 0;
}
#undef SERIO_ADD_UEVENT_VAR
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index b16ebef5b911..611fc3905d00 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -22,23 +22,18 @@
#define HID_USAGE_PAGE_DIGITIZER 0x0d
#define HID_USAGE_PAGE_DESKTOP 0x01
#define HID_USAGE 0x09
-#define HID_USAGE_X 0x30
-#define HID_USAGE_Y 0x31
-#define HID_USAGE_X_TILT 0x3d
-#define HID_USAGE_Y_TILT 0x3e
-#define HID_USAGE_FINGER 0x22
-#define HID_USAGE_STYLUS 0x20
-#define HID_USAGE_CONTACTMAX 0x55
+#define HID_USAGE_X ((HID_USAGE_PAGE_DESKTOP << 16) | 0x30)
+#define HID_USAGE_Y ((HID_USAGE_PAGE_DESKTOP << 16) | 0x31)
+#define HID_USAGE_PRESSURE ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x30)
+#define HID_USAGE_X_TILT ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x3d)
+#define HID_USAGE_Y_TILT ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x3e)
+#define HID_USAGE_FINGER ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x22)
+#define HID_USAGE_STYLUS ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x20)
+#define HID_USAGE_CONTACTMAX ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x55)
#define HID_COLLECTION 0xa1
#define HID_COLLECTION_LOGICAL 0x02
#define HID_COLLECTION_END 0xc0
-enum {
- WCM_UNDEFINED = 0,
- WCM_DESKTOP,
- WCM_DIGITIZER,
-};
-
struct hid_descriptor {
struct usb_descriptor_header header;
__le16 bcdHID;
@@ -305,7 +300,7 @@ static int wacom_parse_hid(struct usb_interface *intf,
char limit = 0;
/* result has to be defined as int for some devices */
int result = 0, touch_max = 0;
- int i = 0, usage = WCM_UNDEFINED, finger = 0, pen = 0;
+ int i = 0, page = 0, finger = 0, pen = 0;
unsigned char *report;
report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL);
@@ -332,134 +327,121 @@ static int wacom_parse_hid(struct usb_interface *intf,
switch (report[i]) {
case HID_USAGE_PAGE:
- switch (report[i + 1]) {
- case HID_USAGE_PAGE_DIGITIZER:
- usage = WCM_DIGITIZER;
- i++;
- break;
-
- case HID_USAGE_PAGE_DESKTOP:
- usage = WCM_DESKTOP;
- i++;
- break;
- }
+ page = report[i + 1];
+ i++;
break;
case HID_USAGE:
- switch (report[i + 1]) {
+ switch (page << 16 | report[i + 1]) {
case HID_USAGE_X:
- if (usage == WCM_DESKTOP) {
- if (finger) {
- features->device_type = BTN_TOOL_FINGER;
- /* touch device at least supports one touch point */
- touch_max = 1;
- switch (features->type) {
- case TABLETPC2FG:
- features->pktlen = WACOM_PKGLEN_TPC2FG;
- break;
-
- case MTSCREEN:
- case WACOM_24HDT:
- features->pktlen = WACOM_PKGLEN_MTOUCH;
- break;
-
- case MTTPC:
- features->pktlen = WACOM_PKGLEN_MTTPC;
- break;
-
- case BAMBOO_PT:
- features->pktlen = WACOM_PKGLEN_BBTOUCH;
- break;
-
- default:
- features->pktlen = WACOM_PKGLEN_GRAPHIRE;
- break;
- }
-
- switch (features->type) {
- case BAMBOO_PT:
- features->x_phy =
- get_unaligned_le16(&report[i + 5]);
- features->x_max =
- get_unaligned_le16(&report[i + 8]);
- i += 15;
- break;
-
- case WACOM_24HDT:
- features->x_max =
- get_unaligned_le16(&report[i + 3]);
- features->x_phy =
- get_unaligned_le16(&report[i + 8]);
- features->unit = report[i - 1];
- features->unitExpo = report[i - 3];
- i += 12;
- break;
-
- default:
- features->x_max =
- get_unaligned_le16(&report[i + 3]);
- features->x_phy =
- get_unaligned_le16(&report[i + 6]);
- features->unit = report[i + 9];
- features->unitExpo = report[i + 11];
- i += 12;
- break;
- }
- } else if (pen) {
- /* penabled only accepts exact bytes of data */
- if (features->type >= TABLETPC)
- features->pktlen = WACOM_PKGLEN_GRAPHIRE;
- features->device_type = BTN_TOOL_PEN;
+ if (finger) {
+ features->device_type = BTN_TOOL_FINGER;
+ /* touch device at least supports one touch point */
+ touch_max = 1;
+ switch (features->type) {
+ case TABLETPC2FG:
+ features->pktlen = WACOM_PKGLEN_TPC2FG;
+ break;
+
+ case MTSCREEN:
+ case WACOM_24HDT:
+ features->pktlen = WACOM_PKGLEN_MTOUCH;
+ break;
+
+ case MTTPC:
+ features->pktlen = WACOM_PKGLEN_MTTPC;
+ break;
+
+ case BAMBOO_PT:
+ features->pktlen = WACOM_PKGLEN_BBTOUCH;
+ break;
+
+ default:
+ features->pktlen = WACOM_PKGLEN_GRAPHIRE;
+ break;
+ }
+
+ switch (features->type) {
+ case BAMBOO_PT:
+ features->x_phy =
+ get_unaligned_le16(&report[i + 5]);
+ features->x_max =
+ get_unaligned_le16(&report[i + 8]);
+ i += 15;
+ break;
+
+ case WACOM_24HDT:
features->x_max =
get_unaligned_le16(&report[i + 3]);
- i += 4;
+ features->x_phy =
+ get_unaligned_le16(&report[i + 8]);
+ features->unit = report[i - 1];
+ features->unitExpo = report[i - 3];
+ i += 12;
+ break;
+
+ default:
+ features->x_max =
+ get_unaligned_le16(&report[i + 3]);
+ features->x_phy =
+ get_unaligned_le16(&report[i + 6]);
+ features->unit = report[i + 9];
+ features->unitExpo = report[i + 11];
+ i += 12;
+ break;
}
+ } else if (pen) {
+ /* penabled only accepts exact bytes of data */
+ if (features->type >= TABLETPC)
+ features->pktlen = WACOM_PKGLEN_GRAPHIRE;
+ features->device_type = BTN_TOOL_PEN;
+ features->x_max =
+ get_unaligned_le16(&report[i + 3]);
+ i += 4;
}
break;
case HID_USAGE_Y:
- if (usage == WCM_DESKTOP) {
- if (finger) {
- switch (features->type) {
- case TABLETPC2FG:
- case MTSCREEN:
- case MTTPC:
- features->y_max =
- get_unaligned_le16(&report[i + 3]);
- features->y_phy =
- get_unaligned_le16(&report[i + 6]);
- i += 7;
- break;
-
- case WACOM_24HDT:
- features->y_max =
- get_unaligned_le16(&report[i + 3]);
- features->y_phy =
- get_unaligned_le16(&report[i - 2]);
- i += 7;
- break;
-
- case BAMBOO_PT:
- features->y_phy =
- get_unaligned_le16(&report[i + 3]);
- features->y_max =
- get_unaligned_le16(&report[i + 6]);
- i += 12;
- break;
-
- default:
- features->y_max =
- features->x_max;
- features->y_phy =
- get_unaligned_le16(&report[i + 3]);
- i += 4;
- break;
- }
- } else if (pen) {
+ if (finger) {
+ switch (features->type) {
+ case TABLETPC2FG:
+ case MTSCREEN:
+ case MTTPC:
+ features->y_max =
+ get_unaligned_le16(&report[i + 3]);
+ features->y_phy =
+ get_unaligned_le16(&report[i + 6]);
+ i += 7;
+ break;
+
+ case WACOM_24HDT:
+ features->y_max =
+ get_unaligned_le16(&report[i + 3]);
+ features->y_phy =
+ get_unaligned_le16(&report[i - 2]);
+ i += 7;
+ break;
+
+ case BAMBOO_PT:
+ features->y_phy =
+ get_unaligned_le16(&report[i + 3]);
+ features->y_max =
+ get_unaligned_le16(&report[i + 6]);
+ i += 12;
+ break;
+
+ default:
features->y_max =
+ features->x_max;
+ features->y_phy =
get_unaligned_le16(&report[i + 3]);
i += 4;
+ break;
}
+ } else if (pen) {
+ features->y_max =
+ get_unaligned_le16(&report[i + 3]);
+ i += 4;
}
break;
@@ -484,12 +466,20 @@ static int wacom_parse_hid(struct usb_interface *intf,
wacom_retrieve_report_data(intf, features);
i++;
break;
+
+ case HID_USAGE_PRESSURE:
+ if (pen) {
+ features->pressure_max =
+ get_unaligned_le16(&report[i + 3]);
+ i += 4;
+ }
+ break;
}
break;
case HID_COLLECTION_END:
/* reset UsagePage and Finger */
- finger = usage = 0;
+ finger = page = 0;
break;
case HID_COLLECTION:
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 05f371df6c40..4822c57a3756 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -178,10 +178,9 @@ static int wacom_ptu_irq(struct wacom_wac *wacom)
static int wacom_dtu_irq(struct wacom_wac *wacom)
{
- struct wacom_features *features = &wacom->features;
- char *data = wacom->data;
+ unsigned char *data = wacom->data;
struct input_dev *input = wacom->input;
- int prox = data[1] & 0x20, pressure;
+ int prox = data[1] & 0x20;
dev_dbg(input->dev.parent,
"%s: received report #%d", __func__, data[0]);
@@ -198,10 +197,7 @@ static int wacom_dtu_irq(struct wacom_wac *wacom)
input_report_key(input, BTN_STYLUS2, data[1] & 0x10);
input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
- pressure = ((data[7] & 0x01) << 8) | data[6];
- if (pressure < 0)
- pressure = features->pressure_max + pressure + 1;
- input_report_abs(input, ABS_PRESSURE, pressure);
+ input_report_abs(input, ABS_PRESSURE, ((data[7] & 0x01) << 8) | data[6]);
input_report_key(input, BTN_TOUCH, data[1] & 0x05);
if (!prox) /* out-prox */
wacom->id[0] = 0;
@@ -906,7 +902,7 @@ static int int_dist(int x1, int y1, int x2, int y2)
static int wacom_24hdt_irq(struct wacom_wac *wacom)
{
struct input_dev *input = wacom->input;
- char *data = wacom->data;
+ unsigned char *data = wacom->data;
int i;
int current_num_contacts = data[61];
int contacts_to_send = 0;
@@ -959,7 +955,7 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom)
static int wacom_mt_touch(struct wacom_wac *wacom)
{
struct input_dev *input = wacom->input;
- char *data = wacom->data;
+ unsigned char *data = wacom->data;
int i;
int current_num_contacts = data[2];
int contacts_to_send = 0;
@@ -1038,7 +1034,7 @@ static int wacom_tpc_mt_touch(struct wacom_wac *wacom)
static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len)
{
- char *data = wacom->data;
+ unsigned char *data = wacom->data;
struct input_dev *input = wacom->input;
bool prox;
int x = 0, y = 0;
@@ -1074,10 +1070,8 @@ static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len)
static int wacom_tpc_pen(struct wacom_wac *wacom)
{
- struct wacom_features *features = &wacom->features;
- char *data = wacom->data;
+ unsigned char *data = wacom->data;
struct input_dev *input = wacom->input;
- int pressure;
bool prox = data[1] & 0x20;
if (!wacom->shared->stylus_in_proximity) /* first in prox */
@@ -1093,10 +1087,7 @@ static int wacom_tpc_pen(struct wacom_wac *wacom)
input_report_key(input, BTN_STYLUS2, data[1] & 0x10);
input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
- pressure = ((data[7] & 0x01) << 8) | data[6];
- if (pressure < 0)
- pressure = features->pressure_max + pressure + 1;
- input_report_abs(input, ABS_PRESSURE, pressure);
+ input_report_abs(input, ABS_PRESSURE, ((data[7] & 0x03) << 8) | data[6]);
input_report_key(input, BTN_TOUCH, data[1] & 0x05);
input_report_key(input, wacom->tool[0], prox);
return 1;
@@ -1107,7 +1098,7 @@ static int wacom_tpc_pen(struct wacom_wac *wacom)
static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
{
- char *data = wacom->data;
+ unsigned char *data = wacom->data;
dev_dbg(wacom->input->dev.parent,
"%s: received report #%d\n", __func__, data[0]);
@@ -1838,7 +1829,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
case DTU:
if (features->type == DTUS) {
input_set_capability(input_dev, EV_MSC, MSC_SERIAL);
- for (i = 0; i < 3; i++)
+ for (i = 0; i < 4; i++)
__set_bit(BTN_0 + i, input_dev->keybit);
}
__set_bit(BTN_TOOL_PEN, input_dev->keybit);
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 68edc9db2c64..b845e9370871 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -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.
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 45a06e495ed2..7f8aa981500d 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -425,7 +425,7 @@ static int ads7845_read12_ser(struct device *dev, unsigned command)
name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct ads7846 *ts = dev_get_drvdata(dev); \
- ssize_t v = ads7846_read12_ser(dev, \
+ ssize_t v = ads7846_read12_ser(&ts->spi->dev, \
READ_12BIT_SER(var)); \
if (v < 0) \
return v; \
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index c949520bd196..57068e8035b5 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -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);
}
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index b76c58dbe30c..0e08545d7298 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -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;
}
diff --git a/drivers/iommu/amd_iommu_v2.c b/drivers/iommu/amd_iommu_v2.c
index 5208828792e6..203b2e6a91cf 100644
--- a/drivers/iommu/amd_iommu_v2.c
+++ b/drivers/iommu/amd_iommu_v2.c
@@ -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);
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 8b89e33a89fe..647c3c7fd742 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -1381,7 +1381,7 @@ static int arm_smmu_alloc_init_pmd(struct arm_smmu_device *smmu, pud_t *pud,
do {
next = pmd_addr_end(addr, end);
- ret = arm_smmu_alloc_init_pte(smmu, pmd, addr, end, pfn,
+ ret = arm_smmu_alloc_init_pte(smmu, pmd, addr, next, pfn,
prot, stage);
phys += next - addr;
} while (pmd++, addr = next, addr < end);
@@ -1499,7 +1499,7 @@ static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova,
ret = arm_smmu_handle_mapping(smmu_domain, iova, 0, size, 0);
arm_smmu_tlb_inv_context(&smmu_domain->root_cfg);
- return ret ? ret : size;
+ return ret ? 0 : size;
}
static phys_addr_t arm_smmu_iova_to_phys(struct iommu_domain *domain,
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index f445c10df8df..39f8b717fe84 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -152,7 +152,8 @@ dmar_alloc_pci_notify_info(struct pci_dev *dev, unsigned long event)
info->seg = pci_domain_nr(dev->bus);
info->level = level;
if (event == BUS_NOTIFY_ADD_DEVICE) {
- for (tmp = dev, level--; tmp; tmp = tmp->bus->self) {
+ for (tmp = dev; tmp; tmp = tmp->bus->self) {
+ level--;
info->path[level].device = PCI_SLOT(tmp->devfn);
info->path[level].function = PCI_FUNC(tmp->devfn);
if (pci_is_root_bus(tmp->bus))
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 69fa7da5e48b..f256ffc02e29 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -1009,11 +1009,13 @@ static struct page *dma_pte_list_pagetables(struct dmar_domain *domain,
if (level == 1)
return freelist;
- for (pte = page_address(pg); !first_pte_in_page(pte); pte++) {
+ pte = page_address(pg);
+ do {
if (dma_pte_present(pte) && !dma_pte_superpage(pte))
freelist = dma_pte_list_pagetables(domain, level - 1,
pte, freelist);
- }
+ pte++;
+ } while (!first_pte_in_page(pte));
return freelist;
}
@@ -2235,7 +2237,9 @@ static struct dmar_domain *get_domain_for_dev(struct device *dev, int gaw)
bridge_devfn = dev_tmp->devfn;
}
spin_lock_irqsave(&device_domain_lock, flags);
- info = dmar_search_domain_by_dev_info(segment, bus, devfn);
+ info = dmar_search_domain_by_dev_info(segment,
+ bridge_bus,
+ bridge_devfn);
if (info) {
iommu = info->iommu;
domain = info->domain;
diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index 41be897df8d5..3899ba7821c5 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -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);
diff --git a/drivers/irqchip/irq-crossbar.c b/drivers/irqchip/irq-crossbar.c
index fc817d28d1fe..3d15d16a7088 100644
--- a/drivers/irqchip/irq-crossbar.c
+++ b/drivers/irqchip/irq-crossbar.c
@@ -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;
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 4300b6606f5e..57d165e026f4 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -246,10 +246,14 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
bool force)
{
void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3);
- unsigned int shift = (gic_irq(d) % 4) * 8;
- unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask);
+ unsigned int cpu, shift = (gic_irq(d) % 4) * 8;
u32 val, mask, bit;
+ if (!force)
+ cpu = cpumask_any_and(mask_val, cpu_online_mask);
+ else
+ cpu = cpumask_first(mask_val);
+
if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids)
return -EINVAL;
diff --git a/drivers/irqchip/irq-vic.c b/drivers/irqchip/irq-vic.c
index 37dab0b472cd..7d35287f9e90 100644
--- a/drivers/irqchip/irq-vic.c
+++ b/drivers/irqchip/irq-vic.c
@@ -24,6 +24,7 @@
#include <linux/list.h>
#include <linux/io.h>
#include <linux/irq.h>
+#include <linux/irqchip/chained_irq.h>
#include <linux/irqdomain.h>
#include <linux/of.h>
#include <linux/of_address.h>
@@ -228,12 +229,17 @@ static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs)
static void vic_handle_irq_cascaded(unsigned int irq, struct irq_desc *desc)
{
u32 stat, hwirq;
+ struct irq_chip *host_chip = irq_desc_get_chip(desc);
struct vic_device *vic = irq_desc_get_handler_data(desc);
+ chained_irq_enter(host_chip, desc);
+
while ((stat = readl_relaxed(vic->base + VIC_IRQ_STATUS))) {
hwirq = ffs(stat) - 1;
generic_handle_irq(irq_find_mapping(vic->domain, hwirq));
}
+
+ chained_irq_exit(host_chip, desc);
}
/*
diff --git a/drivers/irqchip/spear-shirq.c b/drivers/irqchip/spear-shirq.c
index 8527743b5cef..3fdda3a40269 100644
--- a/drivers/irqchip/spear-shirq.c
+++ b/drivers/irqchip/spear-shirq.c
@@ -5,7 +5,7 @@
* Viresh Kumar <viresh.linux@gmail.com>
*
* Copyright (C) 2012 ST Microelectronics
- * Shiraz Hashim <shiraz.hashim@st.com>
+ * Shiraz Hashim <shiraz.linux.kernel@gmail.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
diff --git a/drivers/isdn/hisax/icc.c b/drivers/isdn/hisax/icc.c
index 51dae9167238..96d1df05044f 100644
--- a/drivers/isdn/hisax/icc.c
+++ b/drivers/isdn/hisax/icc.c
@@ -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
}
}
diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c
index 53d487f0c79d..6a7447c304ac 100644
--- a/drivers/isdn/icn/icn.c
+++ b/drivers/isdn/icn/icn.c
@@ -1155,7 +1155,7 @@ icn_command(isdn_ctrl *c, icn_card *card)
ulong a;
ulong flags;
int i;
- char cbuf[60];
+ char cbuf[80];
isdn_ctrl cmd;
icn_cdef cdef;
char __user *arg;
@@ -1309,7 +1309,6 @@ icn_command(isdn_ctrl *c, icn_card *card)
break;
if ((c->arg & 255) < ICN_BCH) {
char *p;
- char dial[50];
char dcode[4];
a = c->arg;
@@ -1321,10 +1320,10 @@ icn_command(isdn_ctrl *c, icn_card *card)
} else
/* Normal Dial */
strcpy(dcode, "CAL");
- strcpy(dial, p);
- sprintf(cbuf, "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1),
- dcode, dial, c->parm.setup.si1,
- c->parm.setup.si2, c->parm.setup.eazmsn);
+ snprintf(cbuf, sizeof(cbuf),
+ "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1),
+ dcode, p, c->parm.setup.si1,
+ c->parm.setup.si2, c->parm.setup.eazmsn);
i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
}
break;
diff --git a/drivers/mcb/mcb-parse.c b/drivers/mcb/mcb-parse.c
index d1278b5f3028..004926955263 100644
--- a/drivers/mcb/mcb-parse.c
+++ b/drivers/mcb/mcb-parse.c
@@ -141,6 +141,7 @@ int chameleon_parse_cells(struct mcb_bus *bus, phys_addr_t mapbase,
default:
pr_err("Invalid chameleon descriptor type 0x%x\n",
dtype);
+ kfree(header);
return -EINVAL;
}
num_cells++;
diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c
index 1bf4a71919ec..5f054c44b485 100644
--- a/drivers/md/dm-cache-target.c
+++ b/drivers/md/dm-cache-target.c
@@ -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))
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 784695d22fde..53b213226c01 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -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.
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index aa009e865871..ebfa411d1a7d 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -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;
}
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index 53728be84dee..242ac2ea5f29 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -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");
diff --git a/drivers/md/dm-verity.c b/drivers/md/dm-verity.c
index 796007a5e0e1..7a7bab8947ae 100644
--- a/drivers/md/dm-verity.c
+++ b/drivers/md/dm-verity.c
@@ -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);
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 8fda38d23e38..237b7e0ddc7a 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -8516,7 +8516,8 @@ static int md_notify_reboot(struct notifier_block *this,
if (mddev_trylock(mddev)) {
if (mddev->pers)
__md_stop_writes(mddev);
- mddev->safemode = 2;
+ if (mddev->persistent)
+ mddev->safemode = 2;
mddev_unlock(mddev);
}
need_delay = 1;
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 33fc408e5eac..cb882aae9e20 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -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 {
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 25247a852912..ad1b9bea446e 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -4370,8 +4370,7 @@ static struct stripe_head *__get_priority_stripe(struct r5conf *conf, int group)
sh->group = NULL;
}
list_del_init(&sh->lru);
- atomic_inc(&sh->count);
- BUG_ON(atomic_read(&sh->count) != 1);
+ BUG_ON(atomic_inc_return(&sh->count) != 1);
return sh;
}
diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c
index e8a1ce204036..cdd7c1b7259b 100644
--- a/drivers/media/i2c/ov7670.c
+++ b/drivers/media/i2c/ov7670.c
@@ -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)
diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
index a4459301b5f8..ee0f57e01b56 100644
--- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c
+++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
@@ -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);
diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index d5a7a135f75d..703560fa5e73 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -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;
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index c137abfa0c54..20f1655e6d75 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -56,7 +56,7 @@ config VIDEO_VIU
config VIDEO_TIMBERDALE
tristate "Support for timberdale Video In/LogiWIN"
- depends on VIDEO_V4L2 && I2C && DMADEVICES
+ depends on MFD_TIMBERDALE && VIDEO_V4L2 && I2C && DMADEVICES
select DMA_ENGINE
select TIMB_DMA
select VIDEO_ADV7180
diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c
index b4f12d00be05..656708252962 100644
--- a/drivers/media/platform/davinci/vpbe_display.c
+++ b/drivers/media/platform/davinci/vpbe_display.c
@@ -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;
}
diff --git a/drivers/media/platform/davinci/vpfe_capture.c b/drivers/media/platform/davinci/vpfe_capture.c
index d762246eabf5..0379cb9f9a9c 100644
--- a/drivers/media/platform/davinci/vpfe_capture.c
+++ b/drivers/media/platform/davinci/vpfe_capture.c
@@ -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 */
diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c
index 756da78bac23..8dea0b84a3ad 100644
--- a/drivers/media/platform/davinci/vpif_capture.c
+++ b/drivers/media/platform/davinci/vpif_capture.c
@@ -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);
diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c
index 0ac841e35aa4..aed41edd0501 100644
--- a/drivers/media/platform/davinci/vpif_display.c
+++ b/drivers/media/platform/davinci/vpif_display.c
@@ -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);
diff --git a/drivers/media/platform/exynos4-is/fimc-core.c b/drivers/media/platform/exynos4-is/fimc-core.c
index da2fc86cc524..25dbf5b05a96 100644
--- a/drivers/media/platform/exynos4-is/fimc-core.c
+++ b/drivers/media/platform/exynos4-is/fimc-core.c
@@ -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,
diff --git a/drivers/media/tuners/fc2580.c b/drivers/media/tuners/fc2580.c
index 3aecaf465094..f0c9c42867de 100644
--- a/drivers/media/tuners/fc2580.c
+++ b/drivers/media/tuners/fc2580.c
@@ -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;
diff --git a/drivers/media/tuners/fc2580_priv.h b/drivers/media/tuners/fc2580_priv.h
index be38a9e637e0..646c99452136 100644
--- a/drivers/media/tuners/fc2580_priv.h
+++ b/drivers/media/tuners/fc2580_priv.h
@@ -22,6 +22,7 @@
#define FC2580_PRIV_H
#include "fc2580.h"
+#include <linux/math64.h>
struct fc2580_reg_val {
u8 reg;
diff --git a/drivers/media/usb/dvb-usb-v2/Makefile b/drivers/media/usb/dvb-usb-v2/Makefile
index 7407b8338ccf..bc38f03394cd 100644
--- a/drivers/media/usb/dvb-usb-v2/Makefile
+++ b/drivers/media/usb/dvb-usb-v2/Makefile
@@ -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
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index 61d196e8b3ab..dcbd392e6efc 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -24,7 +24,6 @@
#include "rtl2830.h"
#include "rtl2832.h"
-#include "rtl2832_sdr.h"
#include "qt1010.h"
#include "mt2060.h"
@@ -36,6 +35,45 @@
#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:
diff --git a/drivers/media/usb/gspca/sonixb.c b/drivers/media/usb/gspca/sonixb.c
index 7277dbd2afcd..ecbcb39feb71 100644
--- a/drivers/media/usb/gspca/sonixb.c
+++ b/drivers/media/usb/gspca/sonixb.c
@@ -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)},
diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 04b2daf567be..7e2411c36419 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -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);
}
diff --git a/drivers/memory/mvebu-devbus.c b/drivers/memory/mvebu-devbus.c
index 110c03627051..b59a17fb7c3e 100644
--- a/drivers/memory/mvebu-devbus.c
+++ b/drivers/memory/mvebu-devbus.c
@@ -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);
diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c
index c9de3d598ea5..1d15735f9ef9 100644
--- a/drivers/mfd/rtsx_pcr.c
+++ b/drivers/mfd/rtsx_pcr.c
@@ -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));
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 1cb74085e410..8baff0effc7d 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -300,8 +300,8 @@ config SGI_GRU_DEBUG
depends on SGI_GRU
default n
---help---
- This option enables addition debugging code for the SGI GRU driver. If
- you are unsure, say N.
+ This option enables additional debugging code for the SGI GRU driver.
+ If you are unsure, say N.
config APDS9802ALS
tristate "Medfield Avago APDS9802 ALS Sensor module"
diff --git a/drivers/misc/genwqe/card_base.h b/drivers/misc/genwqe/card_base.h
index 5e4dbd21f89a..0e608a288603 100644
--- a/drivers/misc/genwqe/card_base.h
+++ b/drivers/misc/genwqe/card_base.h
@@ -337,6 +337,44 @@ enum genwqe_requ_state {
};
/**
+ * struct genwqe_sgl - Scatter gather list describing user-space memory
+ * @sgl: scatter gather list needs to be 128 byte aligned
+ * @sgl_dma_addr: dma address of sgl
+ * @sgl_size: size of area used for sgl
+ * @user_addr: user-space address of memory area
+ * @user_size: size of user-space memory area
+ * @page: buffer for partial pages if needed
+ * @page_dma_addr: dma address partial pages
+ */
+struct genwqe_sgl {
+ dma_addr_t sgl_dma_addr;
+ struct sg_entry *sgl;
+ size_t sgl_size; /* size of sgl */
+
+ void __user *user_addr; /* user-space base-address */
+ size_t user_size; /* size of memory area */
+
+ unsigned long nr_pages;
+ unsigned long fpage_offs;
+ size_t fpage_size;
+ size_t lpage_size;
+
+ void *fpage;
+ dma_addr_t fpage_dma_addr;
+
+ void *lpage;
+ dma_addr_t lpage_dma_addr;
+};
+
+int genwqe_alloc_sync_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl,
+ void __user *user_addr, size_t user_size);
+
+int genwqe_setup_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl,
+ dma_addr_t *dma_list);
+
+int genwqe_free_sync_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl);
+
+/**
* struct ddcb_requ - Kernel internal representation of the DDCB request
* @cmd: User space representation of the DDCB execution request
*/
@@ -347,9 +385,7 @@ struct ddcb_requ {
struct ddcb_queue *queue; /* associated queue */
struct dma_mapping dma_mappings[DDCB_FIXUPS];
- struct sg_entry *sgl[DDCB_FIXUPS];
- dma_addr_t sgl_dma_addr[DDCB_FIXUPS];
- size_t sgl_size[DDCB_FIXUPS];
+ struct genwqe_sgl sgls[DDCB_FIXUPS];
/* kernel/user shared content */
struct genwqe_ddcb_cmd cmd; /* ddcb_no for this request */
@@ -453,22 +489,6 @@ int genwqe_user_vmap(struct genwqe_dev *cd, struct dma_mapping *m,
int genwqe_user_vunmap(struct genwqe_dev *cd, struct dma_mapping *m,
struct ddcb_requ *req);
-struct sg_entry *genwqe_alloc_sgl(struct genwqe_dev *cd, int num_pages,
- dma_addr_t *dma_addr, size_t *sgl_size);
-
-void genwqe_free_sgl(struct genwqe_dev *cd, struct sg_entry *sg_list,
- dma_addr_t dma_addr, size_t size);
-
-int genwqe_setup_sgl(struct genwqe_dev *cd,
- unsigned long offs,
- unsigned long size,
- struct sg_entry *sgl, /* genwqe sgl */
- dma_addr_t dma_addr, size_t sgl_size,
- dma_addr_t *dma_list, int page_offs, int num_pages);
-
-int genwqe_check_sgl(struct genwqe_dev *cd, struct sg_entry *sg_list,
- int size);
-
static inline bool dma_mapping_used(struct dma_mapping *m)
{
if (!m)
diff --git a/drivers/misc/genwqe/card_ddcb.c b/drivers/misc/genwqe/card_ddcb.c
index 6f1acc0ccf88..c8046db2d5a2 100644
--- a/drivers/misc/genwqe/card_ddcb.c
+++ b/drivers/misc/genwqe/card_ddcb.c
@@ -305,6 +305,8 @@ static int enqueue_ddcb(struct genwqe_dev *cd, struct ddcb_queue *queue,
break;
new = (old | DDCB_NEXT_BE32);
+
+ wmb();
icrc_hsi_shi = cmpxchg(&prev_ddcb->icrc_hsi_shi_32, old, new);
if (icrc_hsi_shi == old)
@@ -314,6 +316,8 @@ static int enqueue_ddcb(struct genwqe_dev *cd, struct ddcb_queue *queue,
/* Queue must be re-started by updating QUEUE_OFFSET */
ddcb_mark_tapped(pddcb);
num = (u64)ddcb_no << 8;
+
+ wmb();
__genwqe_writeq(cd, queue->IO_QUEUE_OFFSET, num); /* start queue */
return RET_DDCB_TAPPED;
@@ -1306,7 +1310,7 @@ static int queue_wake_up_all(struct genwqe_dev *cd)
*/
int genwqe_finish_queue(struct genwqe_dev *cd)
{
- int i, rc, in_flight;
+ int i, rc = 0, in_flight;
int waitmax = genwqe_ddcb_software_timeout;
struct pci_dev *pci_dev = cd->pci_dev;
struct ddcb_queue *queue = &cd->queue;
diff --git a/drivers/misc/genwqe/card_dev.c b/drivers/misc/genwqe/card_dev.c
index 2c2c9cc75231..1d2f163a1906 100644
--- a/drivers/misc/genwqe/card_dev.c
+++ b/drivers/misc/genwqe/card_dev.c
@@ -531,7 +531,9 @@ static int do_flash_update(struct genwqe_file *cfile,
case '1':
cmdopts = 0x1C;
break; /* download/erase_first/part_1 */
- case 'v': /* cmdopts = 0x0c (VPD) */
+ case 'v':
+ cmdopts = 0x0C;
+ break; /* download/erase_first/vpd */
default:
return -EINVAL;
}
@@ -665,6 +667,8 @@ static int do_flash_read(struct genwqe_file *cfile,
cmdopts = 0x1A;
break; /* upload/part_1 */
case 'v':
+ cmdopts = 0x0A;
+ break; /* upload/vpd */
default:
return -EINVAL;
}
@@ -836,15 +840,8 @@ static int ddcb_cmd_cleanup(struct genwqe_file *cfile, struct ddcb_requ *req)
__genwqe_del_mapping(cfile, dma_map);
genwqe_user_vunmap(cd, dma_map, req);
}
- if (req->sgl[i] != NULL) {
- genwqe_free_sgl(cd, req->sgl[i],
- req->sgl_dma_addr[i],
- req->sgl_size[i]);
- req->sgl[i] = NULL;
- req->sgl_dma_addr[i] = 0x0;
- req->sgl_size[i] = 0;
- }
-
+ if (req->sgls[i].sgl != NULL)
+ genwqe_free_sync_sgl(cd, &req->sgls[i]);
}
return 0;
}
@@ -913,7 +910,7 @@ static int ddcb_cmd_fixups(struct genwqe_file *cfile, struct ddcb_requ *req)
case ATS_TYPE_SGL_RDWR:
case ATS_TYPE_SGL_RD: {
- int page_offs, nr_pages, offs;
+ int page_offs;
u_addr = be64_to_cpu(*((__be64 *)
&cmd->asiv[asiv_offs]));
@@ -951,27 +948,18 @@ static int ddcb_cmd_fixups(struct genwqe_file *cfile, struct ddcb_requ *req)
page_offs = 0;
}
- offs = offset_in_page(u_addr);
- nr_pages = DIV_ROUND_UP(offs + u_size, PAGE_SIZE);
-
/* create genwqe style scatter gather list */
- req->sgl[i] = genwqe_alloc_sgl(cd, m->nr_pages,
- &req->sgl_dma_addr[i],
- &req->sgl_size[i]);
- if (req->sgl[i] == NULL) {
- rc = -ENOMEM;
+ rc = genwqe_alloc_sync_sgl(cd, &req->sgls[i],
+ (void __user *)u_addr,
+ u_size);
+ if (rc != 0)
goto err_out;
- }
- genwqe_setup_sgl(cd, offs, u_size,
- req->sgl[i],
- req->sgl_dma_addr[i],
- req->sgl_size[i],
- m->dma_list,
- page_offs,
- nr_pages);
+
+ genwqe_setup_sgl(cd, &req->sgls[i],
+ &m->dma_list[page_offs]);
*((__be64 *)&cmd->asiv[asiv_offs]) =
- cpu_to_be64(req->sgl_dma_addr[i]);
+ cpu_to_be64(req->sgls[i].sgl_dma_addr);
break;
}
diff --git a/drivers/misc/genwqe/card_utils.c b/drivers/misc/genwqe/card_utils.c
index 6b1a6ef9f1a8..d049d271699c 100644
--- a/drivers/misc/genwqe/card_utils.c
+++ b/drivers/misc/genwqe/card_utils.c
@@ -275,67 +275,107 @@ static int genwqe_sgl_size(int num_pages)
return roundup(len, PAGE_SIZE);
}
-struct sg_entry *genwqe_alloc_sgl(struct genwqe_dev *cd, int num_pages,
- dma_addr_t *dma_addr, size_t *sgl_size)
+/**
+ * genwqe_alloc_sync_sgl() - Allocate memory for sgl and overlapping pages
+ *
+ * Allocates memory for sgl and overlapping pages. Pages which might
+ * overlap other user-space memory blocks are being cached for DMAs,
+ * such that we do not run into syncronization issues. Data is copied
+ * from user-space into the cached pages.
+ */
+int genwqe_alloc_sync_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl,
+ void __user *user_addr, size_t user_size)
{
+ int rc;
struct pci_dev *pci_dev = cd->pci_dev;
- struct sg_entry *sgl;
- *sgl_size = genwqe_sgl_size(num_pages);
- if (get_order(*sgl_size) > MAX_ORDER) {
+ sgl->fpage_offs = offset_in_page((unsigned long)user_addr);
+ sgl->fpage_size = min_t(size_t, PAGE_SIZE-sgl->fpage_offs, user_size);
+ sgl->nr_pages = DIV_ROUND_UP(sgl->fpage_offs + user_size, PAGE_SIZE);
+ sgl->lpage_size = (user_size - sgl->fpage_size) % PAGE_SIZE;
+
+ dev_dbg(&pci_dev->dev, "[%s] uaddr=%p usize=%8ld nr_pages=%ld "
+ "fpage_offs=%lx fpage_size=%ld lpage_size=%ld\n",
+ __func__, user_addr, user_size, sgl->nr_pages,
+ sgl->fpage_offs, sgl->fpage_size, sgl->lpage_size);
+
+ sgl->user_addr = user_addr;
+ sgl->user_size = user_size;
+ sgl->sgl_size = genwqe_sgl_size(sgl->nr_pages);
+
+ if (get_order(sgl->sgl_size) > MAX_ORDER) {
dev_err(&pci_dev->dev,
"[%s] err: too much memory requested!\n", __func__);
- return NULL;
+ return -ENOMEM;
}
- sgl = __genwqe_alloc_consistent(cd, *sgl_size, dma_addr);
- if (sgl == NULL) {
+ sgl->sgl = __genwqe_alloc_consistent(cd, sgl->sgl_size,
+ &sgl->sgl_dma_addr);
+ if (sgl->sgl == NULL) {
dev_err(&pci_dev->dev,
"[%s] err: no memory available!\n", __func__);
- return NULL;
+ return -ENOMEM;
}
- return sgl;
+ /* Only use buffering on incomplete pages */
+ if ((sgl->fpage_size != 0) && (sgl->fpage_size != PAGE_SIZE)) {
+ sgl->fpage = __genwqe_alloc_consistent(cd, PAGE_SIZE,
+ &sgl->fpage_dma_addr);
+ if (sgl->fpage == NULL)
+ goto err_out;
+
+ /* Sync with user memory */
+ if (copy_from_user(sgl->fpage + sgl->fpage_offs,
+ user_addr, sgl->fpage_size)) {
+ rc = -EFAULT;
+ goto err_out;
+ }
+ }
+ if (sgl->lpage_size != 0) {
+ sgl->lpage = __genwqe_alloc_consistent(cd, PAGE_SIZE,
+ &sgl->lpage_dma_addr);
+ if (sgl->lpage == NULL)
+ goto err_out1;
+
+ /* Sync with user memory */
+ if (copy_from_user(sgl->lpage, user_addr + user_size -
+ sgl->lpage_size, sgl->lpage_size)) {
+ rc = -EFAULT;
+ goto err_out1;
+ }
+ }
+ return 0;
+
+ err_out1:
+ __genwqe_free_consistent(cd, PAGE_SIZE, sgl->fpage,
+ sgl->fpage_dma_addr);
+ err_out:
+ __genwqe_free_consistent(cd, sgl->sgl_size, sgl->sgl,
+ sgl->sgl_dma_addr);
+ return -ENOMEM;
}
-int genwqe_setup_sgl(struct genwqe_dev *cd,
- unsigned long offs,
- unsigned long size,
- struct sg_entry *sgl,
- dma_addr_t dma_addr, size_t sgl_size,
- dma_addr_t *dma_list, int page_offs, int num_pages)
+int genwqe_setup_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl,
+ dma_addr_t *dma_list)
{
int i = 0, j = 0, p;
unsigned long dma_offs, map_offs;
- struct pci_dev *pci_dev = cd->pci_dev;
dma_addr_t prev_daddr = 0;
struct sg_entry *s, *last_s = NULL;
-
- /* sanity checks */
- if (offs > PAGE_SIZE) {
- dev_err(&pci_dev->dev,
- "[%s] too large start offs %08lx\n", __func__, offs);
- return -EFAULT;
- }
- if (sgl_size < genwqe_sgl_size(num_pages)) {
- dev_err(&pci_dev->dev,
- "[%s] sgl_size too small %08lx for %d pages\n",
- __func__, sgl_size, num_pages);
- return -EFAULT;
- }
+ size_t size = sgl->user_size;
dma_offs = 128; /* next block if needed/dma_offset */
- map_offs = offs; /* offset in first page */
+ map_offs = sgl->fpage_offs; /* offset in first page */
- s = &sgl[0]; /* first set of 8 entries */
+ s = &sgl->sgl[0]; /* first set of 8 entries */
p = 0; /* page */
- while (p < num_pages) {
+ while (p < sgl->nr_pages) {
dma_addr_t daddr;
unsigned int size_to_map;
/* always write the chaining entry, cleanup is done later */
j = 0;
- s[j].target_addr = cpu_to_be64(dma_addr + dma_offs);
+ s[j].target_addr = cpu_to_be64(sgl->sgl_dma_addr + dma_offs);
s[j].len = cpu_to_be32(128);
s[j].flags = cpu_to_be32(SG_CHAINED);
j++;
@@ -343,7 +383,17 @@ int genwqe_setup_sgl(struct genwqe_dev *cd,
while (j < 8) {
/* DMA mapping for requested page, offs, size */
size_to_map = min(size, PAGE_SIZE - map_offs);
- daddr = dma_list[page_offs + p] + map_offs;
+
+ if ((p == 0) && (sgl->fpage != NULL)) {
+ daddr = sgl->fpage_dma_addr + map_offs;
+
+ } else if ((p == sgl->nr_pages - 1) &&
+ (sgl->lpage != NULL)) {
+ daddr = sgl->lpage_dma_addr;
+ } else {
+ daddr = dma_list[p] + map_offs;
+ }
+
size -= size_to_map;
map_offs = 0;
@@ -358,7 +408,7 @@ int genwqe_setup_sgl(struct genwqe_dev *cd,
size_to_map);
p++; /* process next page */
- if (p == num_pages)
+ if (p == sgl->nr_pages)
goto fixup; /* nothing to do */
prev_daddr = daddr + size_to_map;
@@ -374,7 +424,7 @@ int genwqe_setup_sgl(struct genwqe_dev *cd,
j++;
p++; /* process next page */
- if (p == num_pages)
+ if (p == sgl->nr_pages)
goto fixup; /* nothing to do */
}
dma_offs += 128;
@@ -395,10 +445,50 @@ int genwqe_setup_sgl(struct genwqe_dev *cd,
return 0;
}
-void genwqe_free_sgl(struct genwqe_dev *cd, struct sg_entry *sg_list,
- dma_addr_t dma_addr, size_t size)
+/**
+ * genwqe_free_sync_sgl() - Free memory for sgl and overlapping pages
+ *
+ * After the DMA transfer has been completed we free the memory for
+ * the sgl and the cached pages. Data is being transfered from cached
+ * pages into user-space buffers.
+ */
+int genwqe_free_sync_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl)
{
- __genwqe_free_consistent(cd, size, sg_list, dma_addr);
+ int rc;
+ struct pci_dev *pci_dev = cd->pci_dev;
+
+ if (sgl->fpage) {
+ if (copy_to_user(sgl->user_addr, sgl->fpage + sgl->fpage_offs,
+ sgl->fpage_size)) {
+ dev_err(&pci_dev->dev, "[%s] err: copying fpage!\n",
+ __func__);
+ rc = -EFAULT;
+ }
+ __genwqe_free_consistent(cd, PAGE_SIZE, sgl->fpage,
+ sgl->fpage_dma_addr);
+ sgl->fpage = NULL;
+ sgl->fpage_dma_addr = 0;
+ }
+ if (sgl->lpage) {
+ if (copy_to_user(sgl->user_addr + sgl->user_size -
+ sgl->lpage_size, sgl->lpage,
+ sgl->lpage_size)) {
+ dev_err(&pci_dev->dev, "[%s] err: copying lpage!\n",
+ __func__);
+ rc = -EFAULT;
+ }
+ __genwqe_free_consistent(cd, PAGE_SIZE, sgl->lpage,
+ sgl->lpage_dma_addr);
+ sgl->lpage = NULL;
+ sgl->lpage_dma_addr = 0;
+ }
+ __genwqe_free_consistent(cd, sgl->sgl_size, sgl->sgl,
+ sgl->sgl_dma_addr);
+
+ sgl->sgl = NULL;
+ sgl->sgl_dma_addr = 0x0;
+ sgl->sgl_size = 0;
+ return rc;
}
/**
diff --git a/drivers/misc/genwqe/genwqe_driver.h b/drivers/misc/genwqe/genwqe_driver.h
index 46e916b36c70..cd5263163a6e 100644
--- a/drivers/misc/genwqe/genwqe_driver.h
+++ b/drivers/misc/genwqe/genwqe_driver.h
@@ -36,7 +36,7 @@
#include <asm/byteorder.h>
#include <linux/genwqe/genwqe_card.h>
-#define DRV_VERS_STRING "2.0.0"
+#define DRV_VERS_STRING "2.0.15"
/*
* Static minor number assignement, until we decide/implement
diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h
index 66f411a6e8ea..cabc04383685 100644
--- a/drivers/misc/mei/hw-me-regs.h
+++ b/drivers/misc/mei/hw-me-regs.h
@@ -115,6 +115,11 @@
#define MEI_DEV_ID_LPT_HR 0x8CBA /* Lynx Point H Refresh */
#define MEI_DEV_ID_WPT_LP 0x9CBA /* Wildcat Point LP */
+
+/* Host Firmware Status Registers in PCI Config Space */
+#define PCI_CFG_HFS_1 0x40
+#define PCI_CFG_HFS_2 0x48
+
/*
* MEI HW Section
*/
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 29b5af8efb71..4e3cba6da3f5 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -455,8 +455,7 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
cl->status = 0;
list_del(&cb->list);
- if (MEI_WRITING == cl->writing_state &&
- cb->fop_type == MEI_FOP_WRITE &&
+ if (cb->fop_type == MEI_FOP_WRITE &&
cl != &dev->iamthif_cl) {
cl_dbg(dev, cl, "MEI WRITE COMPLETE\n");
cl->writing_state = MEI_WRITE_COMPLETE;
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index b35594dbf52f..147413145c97 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -644,8 +644,7 @@ static unsigned int mei_poll(struct file *file, poll_table *wait)
goto out;
}
- if (MEI_WRITE_COMPLETE == cl->writing_state)
- mask |= (POLLIN | POLLRDNORM);
+ mask |= (POLLIN | POLLRDNORM);
out:
mutex_unlock(&dev->device_lock);
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index 1c8fd3a3e135..95889e2e31ff 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -97,15 +97,31 @@ static bool mei_me_quirk_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
u32 reg;
- if (ent->device == MEI_DEV_ID_PBG_1) {
- pci_read_config_dword(pdev, 0x48, &reg);
- /* make sure that bit 9 is up and bit 10 is down */
- if ((reg & 0x600) == 0x200) {
- dev_info(&pdev->dev, "Device doesn't have valid ME Interface\n");
- return false;
- }
+ /* Cougar Point || Patsburg */
+ if (ent->device == MEI_DEV_ID_CPT_1 ||
+ ent->device == MEI_DEV_ID_PBG_1) {
+ pci_read_config_dword(pdev, PCI_CFG_HFS_2, &reg);
+ /* make sure that bit 9 (NM) is up and bit 10 (DM) is down */
+ if ((reg & 0x600) == 0x200)
+ goto no_mei;
}
+
+ /* Lynx Point */
+ if (ent->device == MEI_DEV_ID_LPT_H ||
+ ent->device == MEI_DEV_ID_LPT_W ||
+ ent->device == MEI_DEV_ID_LPT_HR) {
+ /* Read ME FW Status check for SPS Firmware */
+ pci_read_config_dword(pdev, PCI_CFG_HFS_1, &reg);
+ /* if bits [19:16] = 15, running SPS Firmware */
+ if ((reg & 0xf0000) == 0xf0000)
+ goto no_mei;
+ }
+
return true;
+
+no_mei:
+ dev_info(&pdev->dev, "Device doesn't have valid ME Interface\n");
+ return false;
}
/**
* mei_probe - Device Initialization Routine
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 771c60ab4a32..a084edd37af5 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -13,6 +13,7 @@
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/device.h>
+#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/slab.h>
@@ -23,6 +24,7 @@
#include <linux/mmc/pm.h>
#include <linux/mmc/host.h>
#include <linux/mmc/card.h>
+#include <linux/mmc/slot-gpio.h>
#include <linux/amba/bus.h>
#include <linux/clk.h>
#include <linux/scatterlist.h>
@@ -364,7 +366,6 @@ static void mmci_init_sg(struct mmci_host *host, struct mmc_data *data)
#ifdef CONFIG_DMA_ENGINE
static void mmci_dma_setup(struct mmci_host *host)
{
- struct mmci_platform_data *plat = host->plat;
const char *rxname, *txname;
dma_cap_mask_t mask;
@@ -378,25 +379,6 @@ static void mmci_dma_setup(struct mmci_host *host)
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
- if (plat && plat->dma_filter) {
- if (!host->dma_rx_channel && plat->dma_rx_param) {
- host->dma_rx_channel = dma_request_channel(mask,
- plat->dma_filter,
- plat->dma_rx_param);
- /* E.g if no DMA hardware is present */
- if (!host->dma_rx_channel)
- dev_err(mmc_dev(host->mmc), "no RX DMA channel\n");
- }
-
- if (!host->dma_tx_channel && plat->dma_tx_param) {
- host->dma_tx_channel = dma_request_channel(mask,
- plat->dma_filter,
- plat->dma_tx_param);
- if (!host->dma_tx_channel)
- dev_warn(mmc_dev(host->mmc), "no TX DMA channel\n");
- }
- }
-
/*
* If only an RX channel is specified, the driver will
* attempt to use it bidirectionally, however if it is
@@ -444,11 +426,9 @@ static void mmci_dma_setup(struct mmci_host *host)
*/
static inline void mmci_dma_release(struct mmci_host *host)
{
- struct mmci_platform_data *plat = host->plat;
-
if (host->dma_rx_channel)
dma_release_channel(host->dma_rx_channel);
- if (host->dma_tx_channel && plat->dma_tx_param)
+ if (host->dma_tx_channel)
dma_release_channel(host->dma_tx_channel);
host->dma_rx_channel = host->dma_tx_channel = NULL;
}
@@ -1285,7 +1265,7 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
* indicating signal direction for the signals in
* the SD/MMC bus and feedback-clock usage.
*/
- pwr |= host->plat->sigdir;
+ pwr |= host->pwr_reg_add;
if (ios->bus_width == MMC_BUS_WIDTH_4)
pwr &= ~MCI_ST_DATA74DIREN;
@@ -1326,35 +1306,18 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
pm_runtime_put_autosuspend(mmc_dev(mmc));
}
-static int mmci_get_ro(struct mmc_host *mmc)
-{
- struct mmci_host *host = mmc_priv(mmc);
-
- if (host->gpio_wp == -ENOSYS)
- return -ENOSYS;
-
- return gpio_get_value_cansleep(host->gpio_wp);
-}
-
static int mmci_get_cd(struct mmc_host *mmc)
{
struct mmci_host *host = mmc_priv(mmc);
struct mmci_platform_data *plat = host->plat;
- unsigned int status;
+ unsigned int status = mmc_gpio_get_cd(mmc);
- if (host->gpio_cd == -ENOSYS) {
+ if (status == -ENOSYS) {
if (!plat->status)
return 1; /* Assume always present */
status = plat->status(mmc_dev(host->mmc));
- } else
- status = !!gpio_get_value_cansleep(host->gpio_cd)
- ^ plat->cd_invert;
-
- /*
- * Use positive logic throughout - status is zero for no card,
- * non-zero for card inserted.
- */
+ }
return status;
}
@@ -1391,70 +1354,44 @@ static int mmci_sig_volt_switch(struct mmc_host *mmc, struct mmc_ios *ios)
return ret;
}
-static irqreturn_t mmci_cd_irq(int irq, void *dev_id)
-{
- struct mmci_host *host = dev_id;
-
- mmc_detect_change(host->mmc, msecs_to_jiffies(500));
-
- return IRQ_HANDLED;
-}
-
static struct mmc_host_ops mmci_ops = {
.request = mmci_request,
.pre_req = mmci_pre_request,
.post_req = mmci_post_request,
.set_ios = mmci_set_ios,
- .get_ro = mmci_get_ro,
+ .get_ro = mmc_gpio_get_ro,
.get_cd = mmci_get_cd,
.start_signal_voltage_switch = mmci_sig_volt_switch,
};
-#ifdef CONFIG_OF
-static void mmci_dt_populate_generic_pdata(struct device_node *np,
- struct mmci_platform_data *pdata)
+static int mmci_of_parse(struct device_node *np, struct mmc_host *mmc)
{
- int bus_width = 0;
-
- pdata->gpio_wp = of_get_named_gpio(np, "wp-gpios", 0);
- pdata->gpio_cd = of_get_named_gpio(np, "cd-gpios", 0);
+ struct mmci_host *host = mmc_priv(mmc);
+ int ret = mmc_of_parse(mmc);
- if (of_get_property(np, "cd-inverted", NULL))
- pdata->cd_invert = true;
- else
- pdata->cd_invert = false;
+ if (ret)
+ return ret;
- of_property_read_u32(np, "max-frequency", &pdata->f_max);
- if (!pdata->f_max)
- pr_warn("%s has no 'max-frequency' property\n", np->full_name);
+ if (of_get_property(np, "st,sig-dir-dat0", NULL))
+ host->pwr_reg_add |= MCI_ST_DATA0DIREN;
+ if (of_get_property(np, "st,sig-dir-dat2", NULL))
+ host->pwr_reg_add |= MCI_ST_DATA2DIREN;
+ if (of_get_property(np, "st,sig-dir-dat31", NULL))
+ host->pwr_reg_add |= MCI_ST_DATA31DIREN;
+ if (of_get_property(np, "st,sig-dir-dat74", NULL))
+ host->pwr_reg_add |= MCI_ST_DATA74DIREN;
+ if (of_get_property(np, "st,sig-dir-cmd", NULL))
+ host->pwr_reg_add |= MCI_ST_CMDDIREN;
+ if (of_get_property(np, "st,sig-pin-fbclk", NULL))
+ host->pwr_reg_add |= MCI_ST_FBCLKEN;
if (of_get_property(np, "mmc-cap-mmc-highspeed", NULL))
- pdata->capabilities |= MMC_CAP_MMC_HIGHSPEED;
+ mmc->caps |= MMC_CAP_MMC_HIGHSPEED;
if (of_get_property(np, "mmc-cap-sd-highspeed", NULL))
- pdata->capabilities |= MMC_CAP_SD_HIGHSPEED;
+ mmc->caps |= MMC_CAP_SD_HIGHSPEED;
- of_property_read_u32(np, "bus-width", &bus_width);
- switch (bus_width) {
- case 0 :
- /* No bus-width supplied. */
- break;
- case 4 :
- pdata->capabilities |= MMC_CAP_4_BIT_DATA;
- break;
- case 8 :
- pdata->capabilities |= MMC_CAP_8_BIT_DATA;
- break;
- default :
- pr_warn("%s: Unsupported bus width\n", np->full_name);
- }
-}
-#else
-static void mmci_dt_populate_generic_pdata(struct device_node *np,
- struct mmci_platform_data *pdata)
-{
- return;
+ return 0;
}
-#endif
static int mmci_probe(struct amba_device *dev,
const struct amba_id *id)
@@ -1478,26 +1415,17 @@ static int mmci_probe(struct amba_device *dev,
return -ENOMEM;
}
- if (np)
- mmci_dt_populate_generic_pdata(np, plat);
+ mmc = mmc_alloc_host(sizeof(struct mmci_host), &dev->dev);
+ if (!mmc)
+ return -ENOMEM;
- ret = amba_request_regions(dev, DRIVER_NAME);
+ ret = mmci_of_parse(np, mmc);
if (ret)
- goto out;
-
- mmc = mmc_alloc_host(sizeof(struct mmci_host), &dev->dev);
- if (!mmc) {
- ret = -ENOMEM;
- goto rel_regions;
- }
+ goto host_free;
host = mmc_priv(mmc);
host->mmc = mmc;
- host->gpio_wp = -ENOSYS;
- host->gpio_cd = -ENOSYS;
- host->gpio_cd_irq = -1;
-
host->hw_designer = amba_manf(dev);
host->hw_revision = amba_rev(dev);
dev_dbg(mmc_dev(mmc), "designer ID = 0x%02x\n", host->hw_designer);
@@ -1529,10 +1457,11 @@ static int mmci_probe(struct amba_device *dev,
dev_dbg(mmc_dev(mmc), "eventual mclk rate: %u Hz\n",
host->mclk);
}
+
host->phybase = dev->res.start;
- host->base = ioremap(dev->res.start, resource_size(&dev->res));
- if (!host->base) {
- ret = -ENOMEM;
+ host->base = devm_ioremap_resource(&dev->dev, &dev->res);
+ if (IS_ERR(host->base)) {
+ ret = PTR_ERR(host->base);
goto clk_disable;
}
@@ -1546,15 +1475,13 @@ static int mmci_probe(struct amba_device *dev,
else
mmc->f_min = DIV_ROUND_UP(host->mclk, 512);
/*
- * If the platform data supplies a maximum operating
- * frequency, this takes precedence. Else, we fall back
- * to using the module parameter, which has a (low)
- * default value in case it is not specified. Either
- * value must not exceed the clock rate into the block,
- * of course.
+ * If no maximum operating frequency is supplied, fall back to use
+ * the module parameter, which has a (low) default value in case it
+ * is not specified. Either value must not exceed the clock rate into
+ * the block, of course.
*/
- if (plat->f_max)
- mmc->f_max = min(host->mclk, plat->f_max);
+ if (mmc->f_max)
+ mmc->f_max = min(host->mclk, mmc->f_max);
else
mmc->f_max = min(host->mclk, fmax);
dev_dbg(mmc_dev(mmc), "clocking block at %u Hz\n", mmc->f_max);
@@ -1566,8 +1493,15 @@ static int mmci_probe(struct amba_device *dev,
else if (plat->ocr_mask)
dev_warn(mmc_dev(mmc), "Platform OCR mask is ignored\n");
- mmc->caps = plat->capabilities;
- mmc->caps2 = plat->capabilities2;
+ /* DT takes precedence over platform data. */
+ if (!np) {
+ if (!plat->cd_invert)
+ mmc->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
+ mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
+ }
+
+ /* We support these capabilities. */
+ mmc->caps |= MMC_CAP_CMD23;
if (variant->busy_detect) {
mmci_ops.card_busy = mmci_card_busy;
@@ -1579,7 +1513,7 @@ static int mmci_probe(struct amba_device *dev,
mmc->ops = &mmci_ops;
/* We support these PM capabilities. */
- mmc->pm_caps = MMC_PM_KEEP_POWER;
+ mmc->pm_caps |= MMC_PM_KEEP_POWER;
/*
* We can do SGIO
@@ -1616,62 +1550,30 @@ static int mmci_probe(struct amba_device *dev,
writel(0, host->base + MMCIMASK1);
writel(0xfff, host->base + MMCICLEAR);
- if (plat->gpio_cd == -EPROBE_DEFER) {
- ret = -EPROBE_DEFER;
- goto err_gpio_cd;
- }
- if (gpio_is_valid(plat->gpio_cd)) {
- ret = gpio_request(plat->gpio_cd, DRIVER_NAME " (cd)");
- if (ret == 0)
- ret = gpio_direction_input(plat->gpio_cd);
- if (ret == 0)
- host->gpio_cd = plat->gpio_cd;
- else if (ret != -ENOSYS)
- goto err_gpio_cd;
-
- /*
- * A gpio pin that will detect cards when inserted and removed
- * will most likely want to trigger on the edges if it is
- * 0 when ejected and 1 when inserted (or mutatis mutandis
- * for the inverted case) so we request triggers on both
- * edges.
- */
- ret = request_any_context_irq(gpio_to_irq(plat->gpio_cd),
- mmci_cd_irq,
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
- DRIVER_NAME " (cd)", host);
- if (ret >= 0)
- host->gpio_cd_irq = gpio_to_irq(plat->gpio_cd);
- }
- if (plat->gpio_wp == -EPROBE_DEFER) {
- ret = -EPROBE_DEFER;
- goto err_gpio_wp;
+ /* If DT, cd/wp gpios must be supplied through it. */
+ if (!np && gpio_is_valid(plat->gpio_cd)) {
+ ret = mmc_gpio_request_cd(mmc, plat->gpio_cd, 0);
+ if (ret)
+ goto clk_disable;
}
- if (gpio_is_valid(plat->gpio_wp)) {
- ret = gpio_request(plat->gpio_wp, DRIVER_NAME " (wp)");
- if (ret == 0)
- ret = gpio_direction_input(plat->gpio_wp);
- if (ret == 0)
- host->gpio_wp = plat->gpio_wp;
- else if (ret != -ENOSYS)
- goto err_gpio_wp;
+ if (!np && gpio_is_valid(plat->gpio_wp)) {
+ ret = mmc_gpio_request_ro(mmc, plat->gpio_wp);
+ if (ret)
+ goto clk_disable;
}
- if ((host->plat->status || host->gpio_cd != -ENOSYS)
- && host->gpio_cd_irq < 0)
- mmc->caps |= MMC_CAP_NEEDS_POLL;
-
- ret = request_irq(dev->irq[0], mmci_irq, IRQF_SHARED, DRIVER_NAME " (cmd)", host);
+ ret = devm_request_irq(&dev->dev, dev->irq[0], mmci_irq, IRQF_SHARED,
+ DRIVER_NAME " (cmd)", host);
if (ret)
- goto unmap;
+ goto clk_disable;
if (!dev->irq[1])
host->singleirq = true;
else {
- ret = request_irq(dev->irq[1], mmci_pio_irq, IRQF_SHARED,
- DRIVER_NAME " (pio)", host);
+ ret = devm_request_irq(&dev->dev, dev->irq[1], mmci_pio_irq,
+ IRQF_SHARED, DRIVER_NAME " (pio)", host);
if (ret)
- goto irq0_free;
+ goto clk_disable;
}
writel(MCI_IRQENABLE, host->base + MMCIMASK0);
@@ -1693,25 +1595,10 @@ static int mmci_probe(struct amba_device *dev,
return 0;
- irq0_free:
- free_irq(dev->irq[0], host);
- unmap:
- if (host->gpio_wp != -ENOSYS)
- gpio_free(host->gpio_wp);
- err_gpio_wp:
- if (host->gpio_cd_irq >= 0)
- free_irq(host->gpio_cd_irq, host);
- if (host->gpio_cd != -ENOSYS)
- gpio_free(host->gpio_cd);
- err_gpio_cd:
- iounmap(host->base);
clk_disable:
clk_disable_unprepare(host->clk);
host_free:
mmc_free_host(mmc);
- rel_regions:
- amba_release_regions(dev);
- out:
return ret;
}
@@ -1737,92 +1624,46 @@ static int mmci_remove(struct amba_device *dev)
writel(0, host->base + MMCIDATACTRL);
mmci_dma_release(host);
- free_irq(dev->irq[0], host);
- if (!host->singleirq)
- free_irq(dev->irq[1], host);
-
- if (host->gpio_wp != -ENOSYS)
- gpio_free(host->gpio_wp);
- if (host->gpio_cd_irq >= 0)
- free_irq(host->gpio_cd_irq, host);
- if (host->gpio_cd != -ENOSYS)
- gpio_free(host->gpio_cd);
-
- iounmap(host->base);
clk_disable_unprepare(host->clk);
-
mmc_free_host(mmc);
-
- amba_release_regions(dev);
- }
-
- return 0;
-}
-
-#ifdef CONFIG_SUSPEND
-static int mmci_suspend(struct device *dev)
-{
- struct amba_device *adev = to_amba_device(dev);
- struct mmc_host *mmc = amba_get_drvdata(adev);
-
- if (mmc) {
- struct mmci_host *host = mmc_priv(mmc);
- pm_runtime_get_sync(dev);
- writel(0, host->base + MMCIMASK0);
}
return 0;
}
-static int mmci_resume(struct device *dev)
-{
- struct amba_device *adev = to_amba_device(dev);
- struct mmc_host *mmc = amba_get_drvdata(adev);
-
- if (mmc) {
- struct mmci_host *host = mmc_priv(mmc);
- writel(MCI_IRQENABLE, host->base + MMCIMASK0);
- pm_runtime_put(dev);
- }
-
- return 0;
-}
-#endif
-
-#ifdef CONFIG_PM_RUNTIME
+#ifdef CONFIG_PM
static void mmci_save(struct mmci_host *host)
{
unsigned long flags;
- if (host->variant->pwrreg_nopower) {
- spin_lock_irqsave(&host->lock, flags);
+ spin_lock_irqsave(&host->lock, flags);
- writel(0, host->base + MMCIMASK0);
+ writel(0, host->base + MMCIMASK0);
+ if (host->variant->pwrreg_nopower) {
writel(0, host->base + MMCIDATACTRL);
writel(0, host->base + MMCIPOWER);
writel(0, host->base + MMCICLOCK);
- mmci_reg_delay(host);
-
- spin_unlock_irqrestore(&host->lock, flags);
}
+ mmci_reg_delay(host);
+ spin_unlock_irqrestore(&host->lock, flags);
}
static void mmci_restore(struct mmci_host *host)
{
unsigned long flags;
- if (host->variant->pwrreg_nopower) {
- spin_lock_irqsave(&host->lock, flags);
+ spin_lock_irqsave(&host->lock, flags);
+ if (host->variant->pwrreg_nopower) {
writel(host->clk_reg, host->base + MMCICLOCK);
writel(host->datactrl_reg, host->base + MMCIDATACTRL);
writel(host->pwr_reg, host->base + MMCIPOWER);
- writel(MCI_IRQENABLE, host->base + MMCIMASK0);
- mmci_reg_delay(host);
-
- spin_unlock_irqrestore(&host->lock, flags);
}
+ writel(MCI_IRQENABLE, host->base + MMCIMASK0);
+ mmci_reg_delay(host);
+
+ spin_unlock_irqrestore(&host->lock, flags);
}
static int mmci_runtime_suspend(struct device *dev)
@@ -1857,8 +1698,9 @@ static int mmci_runtime_resume(struct device *dev)
#endif
static const struct dev_pm_ops mmci_dev_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(mmci_suspend, mmci_resume)
- SET_RUNTIME_PM_OPS(mmci_runtime_suspend, mmci_runtime_resume, NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
+ SET_PM_RUNTIME_PM_OPS(mmci_runtime_suspend, mmci_runtime_resume, NULL)
};
static struct amba_id mmci_ids[] = {
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index 58b1b8896bf2..347d942d740b 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -13,6 +13,16 @@
#define MCI_PWR_ON 0x03
#define MCI_OD (1 << 6)
#define MCI_ROD (1 << 7)
+/*
+ * The ST Micro version does not have ROD and reuse the voltage registers for
+ * direction settings.
+ */
+#define MCI_ST_DATA2DIREN (1 << 2)
+#define MCI_ST_CMDDIREN (1 << 3)
+#define MCI_ST_DATA0DIREN (1 << 4)
+#define MCI_ST_DATA31DIREN (1 << 5)
+#define MCI_ST_FBCLKEN (1 << 7)
+#define MCI_ST_DATA74DIREN (1 << 8)
#define MMCICLOCK 0x004
#define MCI_CLK_ENABLE (1 << 8)
@@ -176,9 +186,6 @@ struct mmci_host {
struct mmc_data *data;
struct mmc_host *mmc;
struct clk *clk;
- int gpio_cd;
- int gpio_wp;
- int gpio_cd_irq;
bool singleirq;
spinlock_t lock;
@@ -186,6 +193,7 @@ struct mmci_host {
unsigned int mclk;
unsigned int cclk;
u32 pwr_reg;
+ u32 pwr_reg_add;
u32 clk_reg;
u32 datactrl_reg;
u32 busy_status;
diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c
index 5fb994f9a653..0b9ded13a3ae 100644
--- a/drivers/mmc/host/rtsx_pci_sdmmc.c
+++ b/drivers/mmc/host/rtsx_pci_sdmmc.c
@@ -31,28 +31,14 @@
#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;
diff --git a/drivers/mtd/devices/spear_smi.c b/drivers/mtd/devices/spear_smi.c
index 363da96e6891..c4176b0f382d 100644
--- a/drivers/mtd/devices/spear_smi.c
+++ b/drivers/mtd/devices/spear_smi.c
@@ -6,7 +6,7 @@
*
* Copyright © 2010 STMicroelectronics.
* Ashish Priyadarshi
- * Shiraz Hashim <shiraz.hashim@st.com>
+ * Shiraz Hashim <shiraz.linux.kernel@gmail.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
@@ -1089,5 +1089,5 @@ static struct platform_driver spear_smi_driver = {
module_platform_driver(spear_smi_driver);
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Ashish Priyadarshi, Shiraz Hashim <shiraz.hashim@st.com>");
+MODULE_AUTHOR("Ashish Priyadarshi, Shiraz Hashim <shiraz.linux.kernel@gmail.com>");
MODULE_DESCRIPTION("MTD SMI driver for serial nor flash chips");
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
index 4615d79fc93f..b922c8efcf40 100644
--- a/drivers/mtd/nand/davinci_nand.c
+++ b/drivers/mtd/nand/davinci_nand.c
@@ -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);
diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c
index ee774ba3728d..20a667c95da4 100644
--- a/drivers/mtd/ubi/block.c
+++ b/drivers/mtd/ubi/block.c
@@ -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);
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 02317c1c0238..0f3425dac910 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -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);
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 9f69e818b000..93580a47cc54 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -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);
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 69aff72c8957..d3a67896d435 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -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);
}
}
diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
index 724e30fa20b9..832070298446 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -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[] = {
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 0e8b268da0a0..5f6babcfc26e 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -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,
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index b8bdd0acc8f3..00bea320e3b5 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -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
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index a5c8dcfa8357..95e04e2002da 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -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)
@@ -108,11 +110,14 @@
#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 | \
@@ -120,12 +125,19 @@
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)
@@ -139,19 +151,17 @@
#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
diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h
index faa8404162b3..c56f1b1c11ca 100644
--- a/drivers/net/can/c_can/c_can.h
+++ b/drivers/net/can/c_can/c_can.h
@@ -22,14 +22,6 @@
#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];
};
diff --git a/drivers/net/can/c_can/c_can_pci.c b/drivers/net/can/c_can/c_can_pci.c
index bce0be54c2f5..fe5f6303b584 100644
--- a/drivers/net/can/c_can/c_can_pci.c
+++ b/drivers/net/can/c_can/c_can_pci.c
@@ -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:
diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c
index 806d92753427..1df0b322d1e4 100644
--- a/drivers/net/can/c_can/c_can_platform.c
+++ b/drivers/net/can/c_can/c_can_platform.c
@@ -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;
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
index c7a260478749..e318e87e2bfc 100644
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -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
diff --git a/drivers/net/can/sja1000/peak_pci.c b/drivers/net/can/sja1000/peak_pci.c
index c540e3d12e3d..564933ae218c 100644
--- a/drivers/net/can/sja1000/peak_pci.c
+++ b/drivers/net/can/sja1000/peak_pci.c
@@ -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 */
diff --git a/drivers/net/can/sja1000/sja1000_isa.c b/drivers/net/can/sja1000/sja1000_isa.c
index df136a2516c4..014695d7e6a3 100644
--- a/drivers/net/can/sja1000/sja1000_isa.c
+++ b/drivers/net/can/sja1000/sja1000_isa.c
@@ -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) {
diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
index f5b16e0e3a12..dcf9196f6316 100644
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -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. */
diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
index 39b26fe28d10..d7401017a3f1 100644
--- a/drivers/net/ethernet/Kconfig
+++ b/drivers/net/ethernet/Kconfig
@@ -35,6 +35,18 @@ source "drivers/net/ethernet/calxeda/Kconfig"
source "drivers/net/ethernet/chelsio/Kconfig"
source "drivers/net/ethernet/cirrus/Kconfig"
source "drivers/net/ethernet/cisco/Kconfig"
+
+config CX_ECAT
+ tristate "Beckhoff CX5020 EtherCAT master support"
+ depends on PCI
+ ---help---
+ Driver for EtherCAT master module located on CCAT FPGA
+ that can be found on Beckhoff CX5020, and possibly other of CX
+ Beckhoff CX series industrial PCs.
+
+ To compile this driver as a module, choose M here. The module
+ will be called ec_bhf.
+
source "drivers/net/ethernet/davicom/Kconfig"
config DNET
diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
index 545d0b3b9cb4..35190e36c456 100644
--- a/drivers/net/ethernet/Makefile
+++ b/drivers/net/ethernet/Makefile
@@ -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/
diff --git a/drivers/net/ethernet/altera/Kconfig b/drivers/net/ethernet/altera/Kconfig
index 80c1ab74a4b8..fdddba51473e 100644
--- a/drivers/net/ethernet/altera/Kconfig
+++ b/drivers/net/ethernet/altera/Kconfig
@@ -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.
diff --git a/drivers/net/ethernet/altera/Makefile b/drivers/net/ethernet/altera/Makefile
index d4a187e45369..3eff2fd3997e 100644
--- a/drivers/net/ethernet/altera/Makefile
+++ b/drivers/net/ethernet/altera/Makefile
@@ -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__
diff --git a/drivers/net/ethernet/altera/altera_msgdma.c b/drivers/net/ethernet/altera/altera_msgdma.c
index 3df18669ea30..0fb986ba3290 100644
--- a/drivers/net/ethernet/altera/altera_msgdma.c
+++ b/drivers/net/ethernet/altera/altera_msgdma.c
@@ -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);
diff --git a/drivers/net/ethernet/altera/altera_msgdma.h b/drivers/net/ethernet/altera/altera_msgdma.h
index 7f0f5bf2bba2..42cf61c81057 100644
--- a/drivers/net/ethernet/altera/altera_msgdma.h
+++ b/drivers/net/ethernet/altera/altera_msgdma.h
@@ -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__ */
diff --git a/drivers/net/ethernet/altera/altera_msgdmahw.h b/drivers/net/ethernet/altera/altera_msgdmahw.h
index d7b59ba4019c..e335626e1b6b 100644
--- a/drivers/net/ethernet/altera/altera_msgdmahw.h
+++ b/drivers/net/ethernet/altera/altera_msgdmahw.h
@@ -17,15 +17,6 @@
#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)
diff --git a/drivers/net/ethernet/altera/altera_sgdma.c b/drivers/net/ethernet/altera/altera_sgdma.c
index 0ee96639ae44..99cc56f451cf 100644
--- a/drivers/net/ethernet/altera/altera_sgdma.c
+++ b/drivers/net/ethernet/altera/altera_sgdma.c
@@ -20,28 +20,28 @@
#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;
}
diff --git a/drivers/net/ethernet/altera/altera_sgdma.h b/drivers/net/ethernet/altera/altera_sgdma.h
index 07d471729dc4..584977e29ef9 100644
--- a/drivers/net/ethernet/altera/altera_sgdma.h
+++ b/drivers/net/ethernet/altera/altera_sgdma.h
@@ -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__ */
diff --git a/drivers/net/ethernet/altera/altera_sgdmahw.h b/drivers/net/ethernet/altera/altera_sgdmahw.h
index ba3334f35383..85bc33b218d9 100644
--- a/drivers/net/ethernet/altera/altera_sgdmahw.h
+++ b/drivers/net/ethernet/altera/altera_sgdmahw.h
@@ -19,16 +19,16 @@
/* 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 */
diff --git a/drivers/net/ethernet/altera/altera_tse.h b/drivers/net/ethernet/altera/altera_tse.h
index 8feeed05de0e..2adb24d4523c 100644
--- a/drivers/net/ethernet/altera/altera_tse.h
+++ b/drivers/net/ethernet/altera/altera_tse.h
@@ -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__ */
diff --git a/drivers/net/ethernet/altera/altera_tse_ethtool.c b/drivers/net/ethernet/altera/altera_tse_ethtool.c
index 319ca74f5e74..54c25eff7952 100644
--- a/drivers/net/ethernet/altera/altera_tse_ethtool.c
+++ b/drivers/net/ethernet/altera/altera_tse_ethtool.c
@@ -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)
diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c
index c70a29e0b9f7..7330681574d2 100644
--- a/drivers/net/ethernet/altera/altera_tse_main.c
+++ b/drivers/net/ethernet/altera/altera_tse_main.c
@@ -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[] = {
diff --git a/drivers/net/ethernet/altera/altera_utils.c b/drivers/net/ethernet/altera/altera_utils.c
index 70fa13f486b2..d7eeb1713ad2 100644
--- a/drivers/net/ethernet/altera/altera_utils.c
+++ b/drivers/net/ethernet/altera/altera_utils.c
@@ -17,28 +17,28 @@
#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;
}
diff --git a/drivers/net/ethernet/altera/altera_utils.h b/drivers/net/ethernet/altera/altera_utils.h
index ce1db36d3583..baf100ccf587 100644
--- a/drivers/net/ethernet/altera/altera_utils.h
+++ b/drivers/net/ethernet/altera/altera_utils.h
@@ -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__*/
diff --git a/drivers/net/ethernet/arc/emac.h b/drivers/net/ethernet/arc/emac.h
index 928fac6dd10a..53f85bf71526 100644
--- a/drivers/net/ethernet/arc/emac.h
+++ b/drivers/net/ethernet/arc/emac.h
@@ -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;
diff --git a/drivers/net/ethernet/arc/emac_main.c b/drivers/net/ethernet/arc/emac_main.c
index eeecc29cf5b7..d647a7d115ac 100644
--- a/drivers/net/ethernet/arc/emac_main.c
+++ b/drivers/net/ethernet/arc/emac_main.c
@@ -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;
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index a8efb18e42fa..0ab83708b6a1 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -8627,6 +8627,7 @@ bnx2_remove_one(struct pci_dev *pdev)
pci_disable_device(pdev);
}
+#ifdef CONFIG_PM_SLEEP
static int
bnx2_suspend(struct device *device)
{
@@ -8665,7 +8666,6 @@ bnx2_resume(struct device *device)
return 0;
}
-#ifdef CONFIG_PM_SLEEP
static SIMPLE_DEV_PM_OPS(bnx2_pm_ops, bnx2_suspend, bnx2_resume);
#define BNX2_PM_OPS (&bnx2_pm_ops)
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index a78edaccceee..3b0d43154e67 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -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);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
index 5c523b32db70..b8078d50261b 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
@@ -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;
}
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
index 8bf764570eef..6929adba52f9 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
@@ -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; }
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
index 0622884596b2..784c7155b98a 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
@@ -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) {
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index b9f7022f4e81..e5d95c5ce1ad 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -12286,7 +12286,9 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e
if (tg3_flag(tp, MAX_RXPEND_64) &&
tp->rx_pending > 63)
tp->rx_pending = 63;
- tp->rx_jumbo_pending = ering->rx_jumbo_pending;
+
+ if (tg3_flag(tp, JUMBO_RING_ENABLE))
+ tp->rx_jumbo_pending = ering->rx_jumbo_pending;
for (i = 0; i < tp->irq_max; i++)
tp->napi[i].tx_pending = ering->tx_pending;
diff --git a/drivers/net/ethernet/cadence/Kconfig b/drivers/net/ethernet/cadence/Kconfig
index 751d5c7b312d..9e089d24466e 100644
--- a/drivers/net/ethernet/cadence/Kconfig
+++ b/drivers/net/ethernet/cadence/Kconfig
@@ -4,7 +4,7 @@
config NET_CADENCE
bool "Cadence devices"
- depends on HAS_IOMEM
+ 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.
@@ -22,7 +22,7 @@ if NET_CADENCE
config ARM_AT91_ETHER
tristate "AT91RM9200 Ethernet support"
- depends on HAS_DMA
+ depends on HAS_DMA && (ARCH_AT91RM9200 || COMPILE_TEST)
select MACB
---help---
If you wish to compile a kernel for the AT91RM9200 and enable
@@ -30,7 +30,7 @@ config ARM_AT91_ETHER
config MACB
tristate "Cadence MACB/GEM support"
- depends on HAS_DMA
+ 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
diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
index ca97005e24b4..e9daa072ebb4 100644
--- a/drivers/net/ethernet/cadence/macb.c
+++ b/drivers/net/ethernet/cadence/macb.c
@@ -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;
diff --git a/drivers/net/ethernet/chelsio/Kconfig b/drivers/net/ethernet/chelsio/Kconfig
index d40c994a4f6a..570222c33410 100644
--- a/drivers/net/ethernet/chelsio/Kconfig
+++ b/drivers/net/ethernet/chelsio/Kconfig
@@ -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>.
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 6fe58913403a..24e16e3301e0 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -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/chelsio/cxgb4/l2t.c b/drivers/net/ethernet/chelsio/cxgb4/l2t.c
index 81e8402a74b4..8a96572fdde0 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/l2t.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/l2t.c
@@ -154,7 +154,7 @@ static int write_l2e(struct adapter *adap, struct l2t_entry *e, int sync)
req->params = htons(L2T_W_PORT(e->lport) | L2T_W_NOREPLY(!sync));
req->l2t_idx = htons(e->idx);
req->vlan = htons(e->vlan);
- if (e->neigh)
+ if (e->neigh && !(e->neigh->dev->flags & IFF_LOOPBACK))
memcpy(e->dmac, e->neigh->ha, sizeof(e->dmac));
memcpy(req->dst_mac, e->dmac, sizeof(req->dst_mac));
@@ -394,6 +394,8 @@ struct l2t_entry *cxgb4_l2t_get(struct l2t_data *d, struct neighbour *neigh,
if (e) {
spin_lock(&e->lock); /* avoid race with t4_l2t_free */
e->state = L2T_STATE_RESOLVING;
+ if (neigh->dev->flags & IFF_LOOPBACK)
+ memcpy(e->dmac, physdev->dev_addr, sizeof(e->dmac));
memcpy(e->addr, addr, addr_len);
e->ifindex = ifidx;
e->hash = hash;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
index fb2fe65903c2..bba67681aeaa 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
@@ -682,7 +682,7 @@ enum {
SF_RD_ID = 0x9f, /* read ID */
SF_ERASE_SECTOR = 0xd8, /* erase sector */
- FW_MAX_SIZE = 512 * 1024,
+ FW_MAX_SIZE = 16 * SF_SEC_SIZE,
};
/**
diff --git a/drivers/net/ethernet/ec_bhf.c b/drivers/net/ethernet/ec_bhf.c
new file mode 100644
index 000000000000..4884205e56ee
--- /dev/null
+++ b/drivers/net/ethernet/ec_bhf.c
@@ -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>");
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index 8ccaa2520dc3..97db5a7179df 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -374,6 +374,7 @@ enum vf_state {
#define BE_FLAGS_NAPI_ENABLED (1 << 9)
#define BE_FLAGS_QNQ_ASYNC_EVT_RCVD (1 << 11)
#define BE_FLAGS_VXLAN_OFFLOADS (1 << 12)
+#define BE_FLAGS_SETUP_DONE (1 << 13)
#define BE_UC_PMAC_COUNT 30
#define BE_VF_UC_PMAC_COUNT 2
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 3e6df47b6973..dc19bc5dec77 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -2033,11 +2033,13 @@ static void be_tx_compl_clean(struct be_adapter *adapter)
bool dummy_wrb;
int i, pending_txqs;
- /* Wait for a max of 200ms for all the tx-completions to arrive. */
+ /* Stop polling for compls when HW has been silent for 10ms */
do {
pending_txqs = adapter->num_tx_qs;
for_all_tx_queues(adapter, txo, i) {
+ cmpl = 0;
+ num_wrbs = 0;
txq = &txo->q;
while ((txcp = be_tx_compl_get(&txo->cq))) {
end_idx =
@@ -2050,14 +2052,13 @@ static void be_tx_compl_clean(struct be_adapter *adapter)
if (cmpl) {
be_cq_notify(adapter, txo->cq.id, false, cmpl);
atomic_sub(num_wrbs, &txq->used);
- cmpl = 0;
- num_wrbs = 0;
+ timeo = 0;
}
if (atomic_read(&txq->used) == 0)
pending_txqs--;
}
- if (pending_txqs == 0 || ++timeo > 200)
+ if (pending_txqs == 0 || ++timeo > 10 || be_hw_error(adapter))
break;
mdelay(1);
@@ -2725,6 +2726,12 @@ static int be_close(struct net_device *netdev)
struct be_eq_obj *eqo;
int i;
+ /* This protection is needed as be_close() may be called even when the
+ * adapter is in cleared state (after eeh perm failure)
+ */
+ if (!(adapter->flags & BE_FLAGS_SETUP_DONE))
+ return 0;
+
be_roce_dev_close(adapter);
if (adapter->flags & BE_FLAGS_NAPI_ENABLED) {
@@ -3055,6 +3062,7 @@ static int be_clear(struct be_adapter *adapter)
be_clear_queues(adapter);
be_msix_disable(adapter);
+ adapter->flags &= ~BE_FLAGS_SETUP_DONE;
return 0;
}
@@ -3559,6 +3567,7 @@ static int be_setup(struct be_adapter *adapter)
adapter->phy.fc_autoneg = 1;
be_schedule_worker(adapter);
+ adapter->flags |= BE_FLAGS_SETUP_DONE;
return 0;
err:
be_clear(adapter);
@@ -4940,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)
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index 9125d9abf099..e2d42475b006 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -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[] =
{
{
diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c
index 891dbee6e6c1..76d70708f864 100644
--- a/drivers/net/ethernet/freescale/gianfar_ethtool.c
+++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c
@@ -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)))
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c
index 9866f264f55e..f0bbd4246d71 100644
--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c
+++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c
@@ -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;
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.h b/drivers/net/ethernet/intel/e1000e/ich8lan.h
index bead50f9187b..5515126c81c1 100644
--- a/drivers/net/ethernet/intel/e1000e/ich8lan.h
+++ b/drivers/net/ethernet/intel/e1000e/ich8lan.h
@@ -232,16 +232,19 @@
#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 */
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index d50c91e50528..3e69386add04 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -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);
diff --git a/drivers/net/ethernet/intel/e1000e/phy.h b/drivers/net/ethernet/intel/e1000e/phy.h
index 3841bccf058c..537d2780b408 100644
--- a/drivers/net/ethernet/intel/e1000e/phy.h
+++ b/drivers/net/ethernet/intel/e1000e/phy.h
@@ -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
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 861b722c2672..cf0761f08911 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -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 |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c
index 262bdf11d221..81299189a47d 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c
@@ -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;
}
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ptp.c b/drivers/net/ethernet/intel/i40e/i40e_ptp.c
index e33ec6c842b7..e61e63720800 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_ptp.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_ptp.c
@@ -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__);
}
}
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index 0f5d96ad281d..9478ddc66caf 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -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);
diff --git a/drivers/net/ethernet/intel/igb/e1000_i210.c b/drivers/net/ethernet/intel/igb/e1000_i210.c
index db963397cc27..f67f8a170b90 100644
--- a/drivers/net/ethernet/intel/igb/e1000_i210.c
+++ b/drivers/net/ethernet/intel/igb/e1000_i210.c
@@ -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;
diff --git a/drivers/net/ethernet/intel/igb/e1000_mac.c b/drivers/net/ethernet/intel/igb/e1000_mac.c
index 5910a932ea7c..1e0c404db81a 100644
--- a/drivers/net/ethernet/intel/igb/e1000_mac.c
+++ b/drivers/net/ethernet/intel/igb/e1000_mac.c
@@ -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-
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index fb98d4602f9d..16430a8440fa 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -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;
diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c
index 9209d652e1c9..ab25e49365f7 100644
--- a/drivers/net/ethernet/intel/igb/igb_ptp.c
+++ b/drivers/net/ethernet/intel/igb/igb_ptp.c
@@ -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");
}
}
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index 1a12c1dd7a27..c6c4ca7d68e6 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -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);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
index 24fba39e194e..981b8a7b100d 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
@@ -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;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index c4c526b7f99f..d62e7a25cf97 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -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)) {
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
index 23f765263f12..a76af8e28a04 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
@@ -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,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
index 63515a6f67fa..8902ae683457 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
@@ -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)
diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c
index b0c6050479eb..b78378cea5e3 100644
--- a/drivers/net/ethernet/jme.c
+++ b/drivers/net/ethernet/jme.c
@@ -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 |
diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c
index b161a525fc5b..9d5ced263a5e 100644
--- a/drivers/net/ethernet/marvell/mvmdio.c
+++ b/drivers/net/ethernet/marvell/mvmdio.c
@@ -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);
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index d04b1c3c9b85..14786c8bf99e 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -91,7 +91,7 @@
#define MVNETA_RX_MIN_FRAME_SIZE 0x247c
#define MVNETA_SERDES_CFG 0x24A0
#define MVNETA_SGMII_SERDES_PROTO 0x0cc7
-#define MVNETA_RGMII_SERDES_PROTO 0x0667
+#define MVNETA_QSGMII_SERDES_PROTO 0x0667
#define MVNETA_TYPE_PRIO 0x24bc
#define MVNETA_FORCE_UNI BIT(21)
#define MVNETA_TXQ_CMD_1 0x24e4
@@ -2721,29 +2721,44 @@ static void mvneta_conf_mbus_windows(struct mvneta_port *pp,
}
/* Power up the port */
-static void mvneta_port_power_up(struct mvneta_port *pp, int phy_mode)
+static int mvneta_port_power_up(struct mvneta_port *pp, int phy_mode)
{
- u32 val;
+ u32 ctrl;
/* MAC Cause register should be cleared */
mvreg_write(pp, MVNETA_UNIT_INTR_CAUSE, 0);
- if (phy_mode == PHY_INTERFACE_MODE_SGMII)
- mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_SGMII_SERDES_PROTO);
- else
- mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_RGMII_SERDES_PROTO);
+ ctrl = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
- val = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
-
- val |= MVNETA_GMAC2_PCS_ENABLE | MVNETA_GMAC2_PORT_RGMII;
+ /* Even though it might look weird, when we're configured in
+ * SGMII or QSGMII mode, the RGMII bit needs to be set.
+ */
+ switch(phy_mode) {
+ case PHY_INTERFACE_MODE_QSGMII:
+ mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_QSGMII_SERDES_PROTO);
+ ctrl |= MVNETA_GMAC2_PCS_ENABLE | MVNETA_GMAC2_PORT_RGMII;
+ break;
+ case PHY_INTERFACE_MODE_SGMII:
+ mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_SGMII_SERDES_PROTO);
+ ctrl |= MVNETA_GMAC2_PCS_ENABLE | MVNETA_GMAC2_PORT_RGMII;
+ break;
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ ctrl |= MVNETA_GMAC2_PORT_RGMII;
+ break;
+ default:
+ return -EINVAL;
+ }
/* Cancel Port Reset */
- val &= ~MVNETA_GMAC2_PORT_RESET;
- mvreg_write(pp, MVNETA_GMAC_CTRL_2, val);
+ ctrl &= ~MVNETA_GMAC2_PORT_RESET;
+ mvreg_write(pp, MVNETA_GMAC_CTRL_2, ctrl);
while ((mvreg_read(pp, MVNETA_GMAC_CTRL_2) &
MVNETA_GMAC2_PORT_RESET) != 0)
continue;
+
+ return 0;
}
/* Device initialization routine */
@@ -2854,7 +2869,12 @@ static int mvneta_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "can't init eth hal\n");
goto err_free_stats;
}
- mvneta_port_power_up(pp, phy_mode);
+
+ err = mvneta_port_power_up(pp, phy_mode);
+ if (err < 0) {
+ dev_err(&pdev->dev, "can't power up port\n");
+ goto err_deinit;
+ }
dram_target_info = mv_mbus_dram_info();
if (dram_target_info)
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c
index 78099eab7673..92d3249f63f1 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c
@@ -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,
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_cq.c b/drivers/net/ethernet/mellanox/mlx4/en_cq.c
index 70e95324a97d..c2cd8d31bcad 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_cq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_cq.c
@@ -66,7 +66,6 @@ int mlx4_en_create_cq(struct mlx4_en_priv *priv,
cq->ring = ring;
cq->is_tx = mode;
- spin_lock_init(&cq->lock);
/* Allocate HW buffers on provided NUMA node.
* dev->numa_node is used in mtt range allocation flow.
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index f085c2df5e69..7e4b1720c3d1 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -1304,15 +1304,11 @@ static void mlx4_en_netpoll(struct net_device *dev)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
struct mlx4_en_cq *cq;
- unsigned long flags;
int i;
for (i = 0; i < priv->rx_ring_num; i++) {
cq = priv->rx_cq[i];
- spin_lock_irqsave(&cq->lock, flags);
- napi_synchronize(&cq->napi);
- mlx4_en_process_rx_cq(dev, cq, 0);
- spin_unlock_irqrestore(&cq->lock, flags);
+ napi_schedule(&cq->napi);
}
}
#endif
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index f0ae95f66ceb..7cf9dadcb471 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -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);
}
/*
@@ -2301,13 +2301,8 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data)
/* Allow large DMA segments, up to the firmware limit of 1 GB */
dma_set_max_seg_size(&pdev->dev, 1024 * 1024 * 1024);
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (!priv) {
- err = -ENOMEM;
- goto err_release_regions;
- }
-
- dev = &priv->dev;
+ dev = pci_get_drvdata(pdev);
+ priv = mlx4_priv(dev);
dev->pdev = pdev;
INIT_LIST_HEAD(&priv->ctx_list);
spin_lock_init(&priv->ctx_lock);
@@ -2374,10 +2369,10 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data)
} else {
atomic_inc(&pf_loading);
err = pci_enable_sriov(pdev, total_vfs);
- atomic_dec(&pf_loading);
if (err) {
mlx4_err(dev, "Failed to enable SR-IOV, continuing without SR-IOV (err = %d).\n",
err);
+ atomic_dec(&pf_loading);
err = 0;
} else {
mlx4_warn(dev, "Running in master mode\n");
@@ -2445,7 +2440,8 @@ slave_start:
* No return code for this call, just warn the user in case of PCI
* express device capabilities are under-satisfied by the bus.
*/
- mlx4_check_pcie_caps(dev);
+ if (!mlx4_is_slave(dev))
+ mlx4_check_pcie_caps(dev);
/* In master functions, the communication channel must be initialized
* after obtaining its address from fw */
@@ -2535,8 +2531,10 @@ slave_start:
mlx4_sense_init(dev);
mlx4_start_sense(dev);
- priv->pci_dev_data = pci_dev_data;
- pci_set_drvdata(pdev, dev);
+ priv->removed = 0;
+
+ if (mlx4_is_master(dev) && dev->num_vfs)
+ atomic_dec(&pf_loading);
return 0;
@@ -2588,6 +2586,9 @@ err_rel_own:
if (!mlx4_is_slave(dev))
mlx4_free_ownership(dev);
+ if (mlx4_is_master(dev) && dev->num_vfs)
+ atomic_dec(&pf_loading);
+
kfree(priv->dev.dev_vfs);
err_free_dev:
@@ -2604,85 +2605,110 @@ err_disable_pdev:
static int mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
+ struct mlx4_priv *priv;
+ struct mlx4_dev *dev;
+
printk_once(KERN_INFO "%s", mlx4_version);
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ dev = &priv->dev;
+ pci_set_drvdata(pdev, dev);
+ priv->pci_dev_data = id->driver_data;
+
return __mlx4_init_one(pdev, id->driver_data);
}
-static void mlx4_remove_one(struct pci_dev *pdev)
+static void __mlx4_remove_one(struct pci_dev *pdev)
{
struct mlx4_dev *dev = pci_get_drvdata(pdev);
struct mlx4_priv *priv = mlx4_priv(dev);
+ int pci_dev_data;
int p;
- if (dev) {
- /* in SRIOV it is not allowed to unload the pf's
- * driver while there are alive vf's */
- if (mlx4_is_master(dev)) {
- if (mlx4_how_many_lives_vf(dev))
- printk(KERN_ERR "Removing PF when there are assigned VF's !!!\n");
- }
- mlx4_stop_sense(dev);
- mlx4_unregister_device(dev);
+ if (priv->removed)
+ return;
- for (p = 1; p <= dev->caps.num_ports; p++) {
- mlx4_cleanup_port_info(&priv->port[p]);
- mlx4_CLOSE_PORT(dev, p);
- }
+ pci_dev_data = priv->pci_dev_data;
- if (mlx4_is_master(dev))
- mlx4_free_resource_tracker(dev,
- RES_TR_FREE_SLAVES_ONLY);
-
- mlx4_cleanup_counters_table(dev);
- mlx4_cleanup_qp_table(dev);
- mlx4_cleanup_srq_table(dev);
- mlx4_cleanup_cq_table(dev);
- mlx4_cmd_use_polling(dev);
- mlx4_cleanup_eq_table(dev);
- mlx4_cleanup_mcg_table(dev);
- mlx4_cleanup_mr_table(dev);
- mlx4_cleanup_xrcd_table(dev);
- mlx4_cleanup_pd_table(dev);
+ /* in SRIOV it is not allowed to unload the pf's
+ * driver while there are alive vf's */
+ if (mlx4_is_master(dev) && mlx4_how_many_lives_vf(dev))
+ printk(KERN_ERR "Removing PF when there are assigned VF's !!!\n");
+ mlx4_stop_sense(dev);
+ mlx4_unregister_device(dev);
- if (mlx4_is_master(dev))
- mlx4_free_resource_tracker(dev,
- RES_TR_FREE_STRUCTS_ONLY);
-
- iounmap(priv->kar);
- mlx4_uar_free(dev, &priv->driver_uar);
- mlx4_cleanup_uar_table(dev);
- if (!mlx4_is_slave(dev))
- mlx4_clear_steering(dev);
- mlx4_free_eq_table(dev);
- if (mlx4_is_master(dev))
- mlx4_multi_func_cleanup(dev);
- mlx4_close_hca(dev);
- if (mlx4_is_slave(dev))
- mlx4_multi_func_cleanup(dev);
- mlx4_cmd_cleanup(dev);
-
- if (dev->flags & MLX4_FLAG_MSI_X)
- pci_disable_msix(pdev);
- if (dev->flags & MLX4_FLAG_SRIOV) {
- mlx4_warn(dev, "Disabling SR-IOV\n");
- pci_disable_sriov(pdev);
- }
+ for (p = 1; p <= dev->caps.num_ports; p++) {
+ mlx4_cleanup_port_info(&priv->port[p]);
+ mlx4_CLOSE_PORT(dev, p);
+ }
+
+ if (mlx4_is_master(dev))
+ mlx4_free_resource_tracker(dev,
+ RES_TR_FREE_SLAVES_ONLY);
+
+ mlx4_cleanup_counters_table(dev);
+ mlx4_cleanup_qp_table(dev);
+ mlx4_cleanup_srq_table(dev);
+ mlx4_cleanup_cq_table(dev);
+ mlx4_cmd_use_polling(dev);
+ mlx4_cleanup_eq_table(dev);
+ mlx4_cleanup_mcg_table(dev);
+ mlx4_cleanup_mr_table(dev);
+ mlx4_cleanup_xrcd_table(dev);
+ mlx4_cleanup_pd_table(dev);
- if (!mlx4_is_slave(dev))
- mlx4_free_ownership(dev);
+ if (mlx4_is_master(dev))
+ mlx4_free_resource_tracker(dev,
+ RES_TR_FREE_STRUCTS_ONLY);
- kfree(dev->caps.qp0_tunnel);
- kfree(dev->caps.qp0_proxy);
- kfree(dev->caps.qp1_tunnel);
- kfree(dev->caps.qp1_proxy);
- kfree(dev->dev_vfs);
+ iounmap(priv->kar);
+ mlx4_uar_free(dev, &priv->driver_uar);
+ mlx4_cleanup_uar_table(dev);
+ if (!mlx4_is_slave(dev))
+ mlx4_clear_steering(dev);
+ mlx4_free_eq_table(dev);
+ if (mlx4_is_master(dev))
+ mlx4_multi_func_cleanup(dev);
+ mlx4_close_hca(dev);
+ if (mlx4_is_slave(dev))
+ mlx4_multi_func_cleanup(dev);
+ mlx4_cmd_cleanup(dev);
- kfree(priv);
- pci_release_regions(pdev);
- pci_disable_device(pdev);
- pci_set_drvdata(pdev, NULL);
+ if (dev->flags & MLX4_FLAG_MSI_X)
+ pci_disable_msix(pdev);
+ if (dev->flags & MLX4_FLAG_SRIOV) {
+ mlx4_warn(dev, "Disabling SR-IOV\n");
+ pci_disable_sriov(pdev);
+ dev->num_vfs = 0;
}
+
+ if (!mlx4_is_slave(dev))
+ mlx4_free_ownership(dev);
+
+ kfree(dev->caps.qp0_tunnel);
+ kfree(dev->caps.qp0_proxy);
+ kfree(dev->caps.qp1_tunnel);
+ kfree(dev->caps.qp1_proxy);
+ kfree(dev->dev_vfs);
+
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ memset(priv, 0, sizeof(*priv));
+ priv->pci_dev_data = pci_dev_data;
+ priv->removed = 1;
+}
+
+static void mlx4_remove_one(struct pci_dev *pdev)
+{
+ struct mlx4_dev *dev = pci_get_drvdata(pdev);
+ struct mlx4_priv *priv = mlx4_priv(dev);
+
+ __mlx4_remove_one(pdev);
+ kfree(priv);
+ pci_set_drvdata(pdev, NULL);
}
int mlx4_restart_one(struct pci_dev *pdev)
@@ -2692,7 +2718,7 @@ int mlx4_restart_one(struct pci_dev *pdev)
int pci_dev_data;
pci_dev_data = priv->pci_dev_data;
- mlx4_remove_one(pdev);
+ __mlx4_remove_one(pdev);
return __mlx4_init_one(pdev, pci_dev_data);
}
@@ -2747,7 +2773,7 @@ MODULE_DEVICE_TABLE(pci, mlx4_pci_table);
static pci_ers_result_t mlx4_pci_err_detected(struct pci_dev *pdev,
pci_channel_state_t state)
{
- mlx4_remove_one(pdev);
+ __mlx4_remove_one(pdev);
return state == pci_channel_io_perm_failure ?
PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_NEED_RESET;
@@ -2755,11 +2781,11 @@ static pci_ers_result_t mlx4_pci_err_detected(struct pci_dev *pdev,
static pci_ers_result_t mlx4_pci_slot_reset(struct pci_dev *pdev)
{
- const struct pci_device_id *id;
- int ret;
+ struct mlx4_dev *dev = pci_get_drvdata(pdev);
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ int ret;
- id = pci_match_id(mlx4_pci_table, pdev);
- ret = __mlx4_init_one(pdev, id->driver_data);
+ ret = __mlx4_init_one(pdev, priv->pci_dev_data);
return ret ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED;
}
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
index cf8be41abb36..212cea440f90 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
@@ -800,6 +800,7 @@ struct mlx4_priv {
spinlock_t ctx_lock;
int pci_dev_data;
+ int removed;
struct list_head pgdir_list;
struct mutex pgdir_mutex;
@@ -1194,6 +1195,12 @@ int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
struct mlx4_cmd_mailbox *outbox,
struct mlx4_cmd_info *cmd);
+int mlx4_UPDATE_QP_wrapper(struct mlx4_dev *dev, int slave,
+ struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox,
+ struct mlx4_cmd_mailbox *outbox,
+ struct mlx4_cmd_info *cmd);
+
int mlx4_PROMISC_wrapper(struct mlx4_dev *dev, int slave,
struct mlx4_vhcr *vhcr,
struct mlx4_cmd_mailbox *inbox,
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index 7a733c287744..04d9b6fe3e80 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -319,7 +319,6 @@ struct mlx4_en_cq {
struct mlx4_cq mcq;
struct mlx4_hwq_resources wqres;
int ring;
- spinlock_t lock;
struct net_device *dev;
struct napi_struct napi;
int size;
diff --git a/drivers/net/ethernet/mellanox/mlx4/port.c b/drivers/net/ethernet/mellanox/mlx4/port.c
index cfcad26ed40f..b5b3549b0c8d 100644
--- a/drivers/net/ethernet/mellanox/mlx4/port.c
+++ b/drivers/net/ethernet/mellanox/mlx4/port.c
@@ -1106,6 +1106,9 @@ int mlx4_get_slave_from_roce_gid(struct mlx4_dev *dev, int port, u8 *gid,
}
if (found_ix >= 0) {
+ /* Calculate a slave_gid which is the slave number in the gid
+ * table and not a globally unique slave number.
+ */
if (found_ix < MLX4_ROCE_PF_GIDS)
slave_gid = 0;
else if (found_ix < MLX4_ROCE_PF_GIDS + (vf_gids % num_vfs) *
@@ -1118,41 +1121,43 @@ int mlx4_get_slave_from_roce_gid(struct mlx4_dev *dev, int port, u8 *gid,
((vf_gids % num_vfs) * ((vf_gids / num_vfs + 1)))) /
(vf_gids / num_vfs)) + vf_gids % num_vfs + 1;
+ /* Calculate the globally unique slave id */
if (slave_gid) {
struct mlx4_active_ports exclusive_ports;
struct mlx4_active_ports actv_ports;
struct mlx4_slaves_pport slaves_pport_actv;
unsigned max_port_p_one;
- int num_slaves_before = 1;
+ int num_vfs_before = 0;
+ int candidate_slave_gid;
+ /* Calculate how many VFs are on the previous port, if exists */
for (i = 1; i < port; i++) {
bitmap_zero(exclusive_ports.ports, dev->caps.num_ports);
- set_bit(i, exclusive_ports.ports);
+ set_bit(i - 1, exclusive_ports.ports);
slaves_pport_actv =
mlx4_phys_to_slaves_pport_actv(
dev, &exclusive_ports);
- num_slaves_before += bitmap_weight(
+ num_vfs_before += bitmap_weight(
slaves_pport_actv.slaves,
dev->num_vfs + 1);
}
- if (slave_gid < num_slaves_before) {
- bitmap_zero(exclusive_ports.ports, dev->caps.num_ports);
- set_bit(port - 1, exclusive_ports.ports);
- slaves_pport_actv =
- mlx4_phys_to_slaves_pport_actv(
- dev, &exclusive_ports);
- slave_gid += bitmap_weight(
- slaves_pport_actv.slaves,
- dev->num_vfs + 1) -
- num_slaves_before;
- }
- actv_ports = mlx4_get_active_ports(dev, slave_gid);
+ /* candidate_slave_gid isn't necessarily the correct slave, but
+ * it has the same number of ports and is assigned to the same
+ * ports as the real slave we're looking for. On dual port VF,
+ * slave_gid = [single port VFs on port <port>] +
+ * [offset of the current slave from the first dual port VF] +
+ * 1 (for the PF).
+ */
+ candidate_slave_gid = slave_gid + num_vfs_before;
+
+ actv_ports = mlx4_get_active_ports(dev, candidate_slave_gid);
max_port_p_one = find_first_bit(
actv_ports.ports, dev->caps.num_ports) +
bitmap_weight(actv_ports.ports,
dev->caps.num_ports) + 1;
+ /* Calculate the real slave number */
for (i = 1; i < max_port_p_one; i++) {
if (i == port)
continue;
diff --git a/drivers/net/ethernet/mellanox/mlx4/qp.c b/drivers/net/ethernet/mellanox/mlx4/qp.c
index 61d64ebffd56..fbd32af89c7c 100644
--- a/drivers/net/ethernet/mellanox/mlx4/qp.c
+++ b/drivers/net/ethernet/mellanox/mlx4/qp.c
@@ -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;
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
index 3b5f53ef29b2..8f1254a79832 100644
--- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
+++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
@@ -3733,6 +3733,25 @@ static int qp_detach(struct mlx4_dev *dev, struct mlx4_qp *qp,
}
}
+static int mlx4_adjust_port(struct mlx4_dev *dev, int slave,
+ u8 *gid, enum mlx4_protocol prot)
+{
+ int real_port;
+
+ if (prot != MLX4_PROT_ETH)
+ return 0;
+
+ if (dev->caps.steering_mode == MLX4_STEERING_MODE_B0 ||
+ dev->caps.steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) {
+ real_port = mlx4_slave_convert_port(dev, slave, gid[5]);
+ if (real_port < 0)
+ return -EINVAL;
+ gid[5] = real_port;
+ }
+
+ return 0;
+}
+
int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
struct mlx4_vhcr *vhcr,
struct mlx4_cmd_mailbox *inbox,
@@ -3768,6 +3787,10 @@ int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
if (err)
goto ex_detach;
} else {
+ err = mlx4_adjust_port(dev, slave, gid, prot);
+ if (err)
+ goto ex_put;
+
err = rem_mcg_res(dev, slave, rqp, gid, prot, type, &reg_id);
if (err)
goto ex_put;
@@ -3872,6 +3895,60 @@ static int add_eth_header(struct mlx4_dev *dev, int slave,
}
+#define MLX4_UPD_QP_PATH_MASK_SUPPORTED (1ULL << MLX4_UPD_QP_PATH_MASK_MAC_INDEX)
+int mlx4_UPDATE_QP_wrapper(struct mlx4_dev *dev, int slave,
+ struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox,
+ struct mlx4_cmd_mailbox *outbox,
+ struct mlx4_cmd_info *cmd_info)
+{
+ int err;
+ u32 qpn = vhcr->in_modifier & 0xffffff;
+ struct res_qp *rqp;
+ u64 mac;
+ unsigned port;
+ u64 pri_addr_path_mask;
+ struct mlx4_update_qp_context *cmd;
+ int smac_index;
+
+ cmd = (struct mlx4_update_qp_context *)inbox->buf;
+
+ pri_addr_path_mask = be64_to_cpu(cmd->primary_addr_path_mask);
+ if (cmd->qp_mask || cmd->secondary_addr_path_mask ||
+ (pri_addr_path_mask & ~MLX4_UPD_QP_PATH_MASK_SUPPORTED))
+ return -EPERM;
+
+ /* Just change the smac for the QP */
+ err = get_res(dev, slave, qpn, RES_QP, &rqp);
+ if (err) {
+ mlx4_err(dev, "Updating qpn 0x%x for slave %d rejected\n", qpn, slave);
+ return err;
+ }
+
+ port = (rqp->sched_queue >> 6 & 1) + 1;
+ smac_index = cmd->qp_context.pri_path.grh_mylmc;
+ err = mac_find_smac_ix_in_slave(dev, slave, port,
+ smac_index, &mac);
+ if (err) {
+ mlx4_err(dev, "Failed to update qpn 0x%x, MAC is invalid. smac_ix: %d\n",
+ qpn, smac_index);
+ goto err_mac;
+ }
+
+ err = mlx4_cmd(dev, inbox->dma,
+ vhcr->in_modifier, 0,
+ MLX4_CMD_UPDATE_QP, MLX4_CMD_TIME_CLASS_A,
+ MLX4_CMD_NATIVE);
+ if (err) {
+ mlx4_err(dev, "Failed to update qpn on qpn 0x%x, command failed\n", qpn);
+ goto err_mac;
+ }
+
+err_mac:
+ put_res(dev, slave, qpn, RES_QP);
+ return err;
+}
+
int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
struct mlx4_vhcr *vhcr,
struct mlx4_cmd_mailbox *inbox,
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index 7b52a88923ef..f785d01c7d12 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -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);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
index b48737dcd3c5..ba20c721ee97 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
@@ -2139,8 +2139,6 @@ static int qlcnic_83xx_get_nic_configuration(struct qlcnic_adapter *adapter)
ahw->max_mac_filters = nic_info.max_mac_filters;
ahw->max_mtu = nic_info.max_mtu;
- adapter->max_tx_rings = ahw->max_tx_ques;
- adapter->max_sds_rings = ahw->max_rx_ques;
/* eSwitch capability indicates vNIC mode.
* vNIC and SRIOV are mutually exclusive operational modes.
* If SR-IOV capability is detected, SR-IOV physical function
@@ -2161,6 +2159,7 @@ static int qlcnic_83xx_get_nic_configuration(struct qlcnic_adapter *adapter)
int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter)
{
struct qlcnic_hardware_context *ahw = adapter->ahw;
+ u16 max_sds_rings, max_tx_rings;
int ret;
ret = qlcnic_83xx_get_nic_configuration(adapter);
@@ -2173,18 +2172,21 @@ int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter)
if (qlcnic_83xx_config_vnic_opmode(adapter))
return -EIO;
- adapter->max_sds_rings = QLCNIC_MAX_VNIC_SDS_RINGS;
- adapter->max_tx_rings = QLCNIC_MAX_VNIC_TX_RINGS;
+ max_sds_rings = QLCNIC_MAX_VNIC_SDS_RINGS;
+ max_tx_rings = QLCNIC_MAX_VNIC_TX_RINGS;
} else if (ret == QLC_83XX_DEFAULT_OPMODE) {
ahw->nic_mode = QLCNIC_DEFAULT_MODE;
adapter->nic_ops->init_driver = qlcnic_83xx_init_default_driver;
ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry;
- adapter->max_sds_rings = QLCNIC_MAX_SDS_RINGS;
- adapter->max_tx_rings = QLCNIC_MAX_TX_RINGS;
+ max_sds_rings = QLCNIC_MAX_SDS_RINGS;
+ max_tx_rings = QLCNIC_MAX_TX_RINGS;
} else {
return -EIO;
}
+ adapter->max_sds_rings = min(ahw->max_rx_ques, max_sds_rings);
+ adapter->max_tx_rings = min(ahw->max_tx_ques, max_tx_rings);
+
return 0;
}
@@ -2348,15 +2350,16 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
goto disable_intr;
}
+ INIT_DELAYED_WORK(&adapter->idc_aen_work, qlcnic_83xx_idc_aen_work);
+
err = qlcnic_83xx_setup_mbx_intr(adapter);
if (err)
goto disable_mbx_intr;
qlcnic_83xx_clear_function_resources(adapter);
-
- INIT_DELAYED_WORK(&adapter->idc_aen_work, qlcnic_83xx_idc_aen_work);
-
+ qlcnic_dcb_enable(adapter->dcb);
qlcnic_83xx_initialize_nic(adapter, 1);
+ qlcnic_dcb_get_info(adapter->dcb);
/* Configure default, SR-IOV or Virtual NIC mode of operation */
err = qlcnic_83xx_configure_opmode(adapter);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
index 64dcbf33d8f0..c1e11f5715b0 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
@@ -883,8 +883,6 @@ int qlcnic_82xx_get_nic_info(struct qlcnic_adapter *adapter,
npar_info->max_rx_ques = le16_to_cpu(nic_info->max_rx_ques);
npar_info->capabilities = le32_to_cpu(nic_info->capabilities);
npar_info->max_mtu = le16_to_cpu(nic_info->max_mtu);
- adapter->max_tx_rings = npar_info->max_tx_ques;
- adapter->max_sds_rings = npar_info->max_rx_ques;
}
qlcnic_free_mbx_args(&cmd);
@@ -1356,6 +1354,7 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter,
arg2 &= ~BIT_3;
break;
case QLCNIC_ADD_VLAN:
+ arg1 &= ~(0x0ffff << 16);
arg1 |= (BIT_2 | BIT_5);
arg1 |= (esw_cfg->vlan_id << 16);
break;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c
index 7d4f54912bad..a51fe18f09a8 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c
@@ -330,8 +330,6 @@ static int __qlcnic_dcb_attach(struct qlcnic_dcb *dcb)
goto out_free_cfg;
}
- qlcnic_dcb_get_info(dcb);
-
return 0;
out_free_cfg:
kfree(dcb->cfg);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 309d05640883..7e55e88a81bf 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -670,7 +670,7 @@ int qlcnic_setup_tss_rss_intr(struct qlcnic_adapter *adapter)
else
num_msix += adapter->drv_tx_rings;
- if (adapter->drv_rss_rings > 0)
+ if (adapter->drv_rss_rings > 0)
num_msix += adapter->drv_rss_rings;
else
num_msix += adapter->drv_sds_rings;
@@ -686,19 +686,15 @@ int qlcnic_setup_tss_rss_intr(struct qlcnic_adapter *adapter)
return -ENOMEM;
}
-restore:
for (vector = 0; vector < num_msix; vector++)
adapter->msix_entries[vector].entry = vector;
+restore:
err = pci_enable_msix(pdev, adapter->msix_entries, num_msix);
- if (err == 0) {
- adapter->ahw->num_msix = num_msix;
- if (adapter->drv_tss_rings > 0)
- adapter->drv_tx_rings = adapter->drv_tss_rings;
+ if (err > 0) {
+ if (!adapter->drv_tss_rings && !adapter->drv_rss_rings)
+ return -ENOSPC;
- if (adapter->drv_rss_rings > 0)
- adapter->drv_sds_rings = adapter->drv_rss_rings;
- } else {
netdev_info(adapter->netdev,
"Unable to allocate %d MSI-X vectors, Available vectors %d\n",
num_msix, err);
@@ -716,12 +712,20 @@ restore:
"Restoring %d Tx, %d SDS rings for total %d vectors.\n",
adapter->drv_tx_rings, adapter->drv_sds_rings,
num_msix);
- goto restore;
- err = -EIO;
+ goto restore;
+ } else if (err < 0) {
+ return err;
}
- return err;
+ adapter->ahw->num_msix = num_msix;
+ if (adapter->drv_tss_rings > 0)
+ adapter->drv_tx_rings = adapter->drv_tss_rings;
+
+ if (adapter->drv_rss_rings > 0)
+ adapter->drv_sds_rings = adapter->drv_rss_rings;
+
+ return 0;
}
int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
@@ -2202,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)
@@ -2265,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;
@@ -2370,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)
{
@@ -2472,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"
@@ -2528,8 +2567,6 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_free_hw;
}
- qlcnic_dcb_enable(adapter->dcb);
-
if (qlcnic_read_mac_addr(adapter))
dev_warn(&pdev->dev, "failed to read mac addr\n");
@@ -2549,7 +2586,10 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
"Device does not support MSI interrupts\n");
if (qlcnic_82xx_check(adapter)) {
+ qlcnic_dcb_enable(adapter->dcb);
+ qlcnic_dcb_get_info(adapter->dcb);
err = qlcnic_setup_intr(adapter);
+
if (err) {
dev_err(&pdev->dev, "Failed to setup interrupt\n");
goto err_out_disable_msi;
@@ -2929,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)));
@@ -3964,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);
@@ -3989,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);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
index 0638c1810d54..6afe9c1f5ab9 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
@@ -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;
}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c
index 14f748cbf0de..280137991544 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c
@@ -461,6 +461,16 @@ static int qlcnic_pci_sriov_disable(struct qlcnic_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
+ if (pci_vfs_assigned(adapter->pdev)) {
+ netdev_err(adapter->netdev,
+ "SR-IOV VFs belonging to port %d are assigned to VMs. SR-IOV can not be disabled on this port\n",
+ adapter->portnum);
+ netdev_info(adapter->netdev,
+ "Please detach SR-IOV VFs belonging to port %d from VMs, and then try to disable SR-IOV on this port\n",
+ adapter->portnum);
+ return -EPERM;
+ }
+
rtnl_lock();
if (netif_running(netdev))
__qlcnic_down(adapter, netdev);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
index 448d156c3d08..cd346e27f2e1 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
@@ -354,7 +354,7 @@ int qlcnic_is_valid_nic_func(struct qlcnic_adapter *adapter, u8 pci_func)
{
int i;
- for (i = 0; i < adapter->ahw->max_vnic_func; i++) {
+ for (i = 0; i < adapter->ahw->total_nic_func; i++) {
if (adapter->npars[i].pci_func == pci_func)
return i;
}
@@ -720,6 +720,7 @@ static ssize_t qlcnic_sysfs_read_npar_config(struct file *file,
struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
struct qlcnic_npar_func_cfg *np_cfg;
struct qlcnic_info nic_info;
+ u8 pci_func;
int i, ret;
u32 count;
@@ -729,26 +730,28 @@ static ssize_t qlcnic_sysfs_read_npar_config(struct file *file,
count = size / sizeof(struct qlcnic_npar_func_cfg);
for (i = 0; i < adapter->ahw->total_nic_func; i++) {
- if (qlcnic_is_valid_nic_func(adapter, i) < 0)
- continue;
if (adapter->npars[i].pci_func >= count) {
dev_dbg(dev, "%s: Total nic functions[%d], App sent function count[%d]\n",
__func__, adapter->ahw->total_nic_func, count);
continue;
}
- ret = qlcnic_get_nic_info(adapter, &nic_info, i);
- if (ret)
- return ret;
if (!adapter->npars[i].eswitch_status)
continue;
- np_cfg[i].pci_func = i;
- np_cfg[i].op_mode = (u8)nic_info.op_mode;
- np_cfg[i].port_num = nic_info.phys_port;
- np_cfg[i].fw_capab = nic_info.capabilities;
- np_cfg[i].min_bw = nic_info.min_tx_bw;
- np_cfg[i].max_bw = nic_info.max_tx_bw;
- np_cfg[i].max_tx_queues = nic_info.max_tx_ques;
- np_cfg[i].max_rx_queues = nic_info.max_rx_ques;
+ pci_func = adapter->npars[i].pci_func;
+ if (qlcnic_is_valid_nic_func(adapter, pci_func) < 0)
+ continue;
+ ret = qlcnic_get_nic_info(adapter, &nic_info, pci_func);
+ if (ret)
+ return ret;
+
+ np_cfg[pci_func].pci_func = pci_func;
+ np_cfg[pci_func].op_mode = (u8)nic_info.op_mode;
+ np_cfg[pci_func].port_num = nic_info.phys_port;
+ np_cfg[pci_func].fw_capab = nic_info.capabilities;
+ np_cfg[pci_func].min_bw = nic_info.min_tx_bw;
+ np_cfg[pci_func].max_bw = nic_info.max_tx_bw;
+ np_cfg[pci_func].max_tx_queues = nic_info.max_tx_ques;
+ np_cfg[pci_func].max_rx_queues = nic_info.max_rx_ques;
}
return size;
}
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h b/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h
index 6203c7d8550f..45019649bbbd 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h
@@ -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);
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c
index c4da7a2b002a..58c35692560e 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c
@@ -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)
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.c
index e896dbbd2e15..2686bb5b6765 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.c
@@ -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,
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.h b/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.h
index 838cb9fb0ea9..18609324db72 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.h
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.h
@@ -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);
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_dma.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_dma.c
index 4d989ff6c978..bb9b5b8afc5f 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_dma.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_dma.c
@@ -23,21 +23,8 @@
/* 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.
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
index 27e8c824b204..82a9a983869f 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
@@ -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);
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c
index 01af2cbb479d..43ccb4a6de15 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c
@@ -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;
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_reg.h b/drivers/net/ethernet/samsung/sxgbe/sxgbe_reg.h
index 5a89acb4c505..56f8bf5a3f1b 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_reg.h
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_reg.h
@@ -52,6 +52,10 @@
#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
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index 21c20ea0dad0..b5ed30a39144 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -738,8 +738,11 @@ static int efx_ef10_reset(struct efx_nic *efx, enum reset_type reset_type)
/* If it was a port reset, trigger reallocation of MC resources.
* Note that on an MC reset nothing needs to be done now because we'll
* detect the MC reset later and handle it then.
+ * For an FLR, we never get an MC reset event, but the MC has reset all
+ * resources assigned to us, so we have to trigger reallocation now.
*/
- if (reset_type == RESET_TYPE_ALL && !rc)
+ if ((reset_type == RESET_TYPE_ALL ||
+ reset_type == RESET_TYPE_MCDI_TIMEOUT) && !rc)
efx_ef10_reset_mc_allocations(efx);
return rc;
}
@@ -2141,6 +2144,11 @@ static int efx_ef10_fini_dmaq(struct efx_nic *efx)
return 0;
}
+static void efx_ef10_prepare_flr(struct efx_nic *efx)
+{
+ atomic_set(&efx->active_queues, 0);
+}
+
static bool efx_ef10_filter_equal(const struct efx_filter_spec *left,
const struct efx_filter_spec *right)
{
@@ -3603,6 +3611,8 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
.probe_port = efx_mcdi_port_probe,
.remove_port = efx_mcdi_port_remove,
.fini_dmaq = efx_ef10_fini_dmaq,
+ .prepare_flr = efx_ef10_prepare_flr,
+ .finish_flr = efx_port_dummy_op_void,
.describe_stats = efx_ef10_describe_stats,
.update_stats = efx_ef10_update_stats,
.start_stats = efx_mcdi_mac_start_stats,
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 57b971e5e6b2..63d595fd3cc5 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -76,6 +76,7 @@ const char *const efx_reset_type_names[] = {
[RESET_TYPE_RECOVER_OR_ALL] = "RECOVER_OR_ALL",
[RESET_TYPE_WORLD] = "WORLD",
[RESET_TYPE_RECOVER_OR_DISABLE] = "RECOVER_OR_DISABLE",
+ [RESET_TYPE_MC_BIST] = "MC_BIST",
[RESET_TYPE_DISABLE] = "DISABLE",
[RESET_TYPE_TX_WATCHDOG] = "TX_WATCHDOG",
[RESET_TYPE_INT_ERROR] = "INT_ERROR",
@@ -83,7 +84,7 @@ const char *const efx_reset_type_names[] = {
[RESET_TYPE_DMA_ERROR] = "DMA_ERROR",
[RESET_TYPE_TX_SKIP] = "TX_SKIP",
[RESET_TYPE_MC_FAILURE] = "MC_FAILURE",
- [RESET_TYPE_MC_BIST] = "MC_BIST",
+ [RESET_TYPE_MCDI_TIMEOUT] = "MCDI_TIMEOUT (FLR)",
};
/* Reset workqueue. If any NIC has a hardware failure then a reset will be
@@ -1739,7 +1740,8 @@ static void efx_start_all(struct efx_nic *efx)
/* Check that it is appropriate to restart the interface. All
* of these flags are safe to read under just the rtnl lock */
- if (efx->port_enabled || !netif_running(efx->net_dev))
+ if (efx->port_enabled || !netif_running(efx->net_dev) ||
+ efx->reset_pending)
return;
efx_start_port(efx);
@@ -2334,6 +2336,9 @@ void efx_reset_down(struct efx_nic *efx, enum reset_type method)
{
EFX_ASSERT_RESET_SERIALISED(efx);
+ if (method == RESET_TYPE_MCDI_TIMEOUT)
+ efx->type->prepare_flr(efx);
+
efx_stop_all(efx);
efx_disable_interrupts(efx);
@@ -2354,6 +2359,10 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok)
EFX_ASSERT_RESET_SERIALISED(efx);
+ if (method == RESET_TYPE_MCDI_TIMEOUT)
+ efx->type->finish_flr(efx);
+
+ /* Ensure that SRAM is initialised even if we're disabling the device */
rc = efx->type->init(efx);
if (rc) {
netif_err(efx, drv, efx->net_dev, "failed to initialise NIC\n");
@@ -2417,7 +2426,10 @@ int efx_reset(struct efx_nic *efx, enum reset_type method)
/* Clear flags for the scopes we covered. We assume the NIC and
* driver are now quiescent so that there is no race here.
*/
- efx->reset_pending &= -(1 << (method + 1));
+ if (method < RESET_TYPE_MAX_METHOD)
+ efx->reset_pending &= -(1 << (method + 1));
+ else /* it doesn't fit into the well-ordered scope hierarchy */
+ __clear_bit(method, &efx->reset_pending);
/* Reinitialise bus-mastering, which may have been turned off before
* the reset was scheduled. This is still appropriate, even in the
@@ -2546,6 +2558,7 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type)
case RESET_TYPE_DISABLE:
case RESET_TYPE_RECOVER_OR_DISABLE:
case RESET_TYPE_MC_BIST:
+ case RESET_TYPE_MCDI_TIMEOUT:
method = type;
netif_dbg(efx, drv, efx->net_dev, "scheduling %s reset\n",
RESET_TYPE(method));
diff --git a/drivers/net/ethernet/sfc/enum.h b/drivers/net/ethernet/sfc/enum.h
index 75ef7ef6450b..d1dbb5fb31bb 100644
--- a/drivers/net/ethernet/sfc/enum.h
+++ b/drivers/net/ethernet/sfc/enum.h
@@ -143,6 +143,7 @@ enum efx_loopback_mode {
* @RESET_TYPE_WORLD: Reset as much as possible
* @RESET_TYPE_RECOVER_OR_DISABLE: Try to recover. Apply RESET_TYPE_DISABLE if
* unsuccessful.
+ * @RESET_TYPE_MC_BIST: MC entering BIST mode.
* @RESET_TYPE_DISABLE: Reset datapath, MAC and PHY; leave NIC disabled
* @RESET_TYPE_TX_WATCHDOG: reset due to TX watchdog
* @RESET_TYPE_INT_ERROR: reset due to internal error
@@ -150,14 +151,16 @@ enum efx_loopback_mode {
* @RESET_TYPE_DMA_ERROR: DMA error
* @RESET_TYPE_TX_SKIP: hardware completed empty tx descriptors
* @RESET_TYPE_MC_FAILURE: MC reboot/assertion
+ * @RESET_TYPE_MCDI_TIMEOUT: MCDI timeout.
*/
enum reset_type {
- RESET_TYPE_INVISIBLE = 0,
- RESET_TYPE_RECOVER_OR_ALL = 1,
- RESET_TYPE_ALL = 2,
- RESET_TYPE_WORLD = 3,
- RESET_TYPE_RECOVER_OR_DISABLE = 4,
- RESET_TYPE_DISABLE = 5,
+ RESET_TYPE_INVISIBLE,
+ RESET_TYPE_RECOVER_OR_ALL,
+ RESET_TYPE_ALL,
+ RESET_TYPE_WORLD,
+ RESET_TYPE_RECOVER_OR_DISABLE,
+ RESET_TYPE_MC_BIST,
+ RESET_TYPE_DISABLE,
RESET_TYPE_MAX_METHOD,
RESET_TYPE_TX_WATCHDOG,
RESET_TYPE_INT_ERROR,
@@ -165,7 +168,13 @@ enum reset_type {
RESET_TYPE_DMA_ERROR,
RESET_TYPE_TX_SKIP,
RESET_TYPE_MC_FAILURE,
- RESET_TYPE_MC_BIST,
+ /* RESET_TYPE_MCDI_TIMEOUT is actually a method, not just a reason, but
+ * it doesn't fit the scope hierarchy (not well-ordered by inclusion).
+ * We encode this by having its enum value be greater than
+ * RESET_TYPE_MAX_METHOD. This also prevents issuing it with
+ * efx_ioctl_reset.
+ */
+ RESET_TYPE_MCDI_TIMEOUT,
RESET_TYPE_MAX,
};
diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c
index 8ec20b713cc6..fae25a418647 100644
--- a/drivers/net/ethernet/sfc/falcon.c
+++ b/drivers/net/ethernet/sfc/falcon.c
@@ -2696,6 +2696,8 @@ const struct efx_nic_type falcon_a1_nic_type = {
.fini_dmaq = efx_farch_fini_dmaq,
.prepare_flush = falcon_prepare_flush,
.finish_flush = efx_port_dummy_op_void,
+ .prepare_flr = efx_port_dummy_op_void,
+ .finish_flr = efx_farch_finish_flr,
.describe_stats = falcon_describe_nic_stats,
.update_stats = falcon_update_nic_stats,
.start_stats = falcon_start_nic_stats,
@@ -2790,6 +2792,8 @@ const struct efx_nic_type falcon_b0_nic_type = {
.fini_dmaq = efx_farch_fini_dmaq,
.prepare_flush = falcon_prepare_flush,
.finish_flush = efx_port_dummy_op_void,
+ .prepare_flr = efx_port_dummy_op_void,
+ .finish_flr = efx_farch_finish_flr,
.describe_stats = falcon_describe_nic_stats,
.update_stats = falcon_update_nic_stats,
.start_stats = falcon_start_nic_stats,
diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c
index a08761360cdf..0537381cd2f6 100644
--- a/drivers/net/ethernet/sfc/farch.c
+++ b/drivers/net/ethernet/sfc/farch.c
@@ -741,6 +741,28 @@ int efx_farch_fini_dmaq(struct efx_nic *efx)
return rc;
}
+/* Reset queue and flush accounting after FLR
+ *
+ * One possible cause of FLR recovery is that DMA may be failing (eg. if bus
+ * mastering was disabled), in which case we don't receive (RXQ) flush
+ * completion events. This means that efx->rxq_flush_outstanding remained at 4
+ * after the FLR; also, efx->active_queues was non-zero (as no flush completion
+ * events were received, and we didn't go through efx_check_tx_flush_complete())
+ * If we don't fix this up, on the next call to efx_realloc_channels() we won't
+ * flush any RX queues because efx->rxq_flush_outstanding is at the limit of 4
+ * for batched flush requests; and the efx->active_queues gets messed up because
+ * we keep incrementing for the newly initialised queues, but it never went to
+ * zero previously. Then we get a timeout every time we try to restart the
+ * queues, as it doesn't go back to zero when we should be flushing the queues.
+ */
+void efx_farch_finish_flr(struct efx_nic *efx)
+{
+ atomic_set(&efx->rxq_flush_pending, 0);
+ atomic_set(&efx->rxq_flush_outstanding, 0);
+ atomic_set(&efx->active_queues, 0);
+}
+
+
/**************************************************************************
*
* Event queue processing
diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c
index 7bd4b14bf3b3..5239cf9bdc56 100644
--- a/drivers/net/ethernet/sfc/mcdi.c
+++ b/drivers/net/ethernet/sfc/mcdi.c
@@ -52,12 +52,7 @@ static void efx_mcdi_timeout_async(unsigned long context);
static int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating,
bool *was_attached_out);
static bool efx_mcdi_poll_once(struct efx_nic *efx);
-
-static inline struct efx_mcdi_iface *efx_mcdi(struct efx_nic *efx)
-{
- EFX_BUG_ON_PARANOID(!efx->mcdi);
- return &efx->mcdi->iface;
-}
+static void efx_mcdi_abandon(struct efx_nic *efx);
int efx_mcdi_init(struct efx_nic *efx)
{
@@ -558,6 +553,8 @@ static int _efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen,
rc = 0;
}
+ efx_mcdi_abandon(efx);
+
/* Close the race with efx_mcdi_ev_cpl() executing just too late
* and completing a request we've just cancelled, by ensuring
* that the seqno check therein fails.
@@ -672,6 +669,9 @@ int efx_mcdi_rpc_start(struct efx_nic *efx, unsigned cmd,
if (efx->mc_bist_for_other_fn)
return -ENETDOWN;
+ if (mcdi->mode == MCDI_MODE_FAIL)
+ return -ENETDOWN;
+
efx_mcdi_acquire_sync(mcdi);
efx_mcdi_send_request(efx, cmd, inbuf, inlen);
return 0;
@@ -812,7 +812,11 @@ void efx_mcdi_mode_poll(struct efx_nic *efx)
return;
mcdi = efx_mcdi(efx);
- if (mcdi->mode == MCDI_MODE_POLL)
+ /* If already in polling mode, nothing to do.
+ * If in fail-fast state, don't switch to polled completion.
+ * FLR recovery will do that later.
+ */
+ if (mcdi->mode == MCDI_MODE_POLL || mcdi->mode == MCDI_MODE_FAIL)
return;
/* We can switch from event completion to polled completion, because
@@ -841,8 +845,8 @@ void efx_mcdi_flush_async(struct efx_nic *efx)
mcdi = efx_mcdi(efx);
- /* We must be in polling mode so no more requests can be queued */
- BUG_ON(mcdi->mode != MCDI_MODE_POLL);
+ /* We must be in poll or fail mode so no more requests can be queued */
+ BUG_ON(mcdi->mode == MCDI_MODE_EVENTS);
del_timer_sync(&mcdi->async_timer);
@@ -875,8 +879,11 @@ void efx_mcdi_mode_event(struct efx_nic *efx)
return;
mcdi = efx_mcdi(efx);
-
- if (mcdi->mode == MCDI_MODE_EVENTS)
+ /* If already in event completion mode, nothing to do.
+ * If in fail-fast state, don't switch to event completion. FLR
+ * recovery will do that later.
+ */
+ if (mcdi->mode == MCDI_MODE_EVENTS || mcdi->mode == MCDI_MODE_FAIL)
return;
/* We can't switch from polled to event completion in the middle of a
@@ -966,6 +973,19 @@ static void efx_mcdi_ev_bist(struct efx_nic *efx)
spin_unlock(&mcdi->iface_lock);
}
+/* MCDI timeouts seen, so make all MCDI calls fail-fast and issue an FLR to try
+ * to recover.
+ */
+static void efx_mcdi_abandon(struct efx_nic *efx)
+{
+ struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
+
+ if (xchg(&mcdi->mode, MCDI_MODE_FAIL) == MCDI_MODE_FAIL)
+ return; /* it had already been done */
+ netif_dbg(efx, hw, efx->net_dev, "MCDI is timing out; trying to recover\n");
+ efx_schedule_reset(efx, RESET_TYPE_MCDI_TIMEOUT);
+}
+
/* Called from falcon_process_eventq for MCDI events */
void efx_mcdi_process_event(struct efx_channel *channel,
efx_qword_t *event)
@@ -1512,6 +1532,19 @@ int efx_mcdi_reset(struct efx_nic *efx, enum reset_type method)
{
int rc;
+ /* If MCDI is down, we can't handle_assertion */
+ if (method == RESET_TYPE_MCDI_TIMEOUT) {
+ rc = pci_reset_function(efx->pci_dev);
+ if (rc)
+ return rc;
+ /* Re-enable polled MCDI completion */
+ if (efx->mcdi) {
+ struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
+ mcdi->mode = MCDI_MODE_POLL;
+ }
+ return 0;
+ }
+
/* Recover from a failed assertion pre-reset */
rc = efx_mcdi_handle_assertion(efx);
if (rc)
diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h
index 52931aebf3c3..56465f7465a2 100644
--- a/drivers/net/ethernet/sfc/mcdi.h
+++ b/drivers/net/ethernet/sfc/mcdi.h
@@ -28,9 +28,16 @@ enum efx_mcdi_state {
MCDI_STATE_COMPLETED,
};
+/**
+ * enum efx_mcdi_mode - MCDI transaction mode
+ * @MCDI_MODE_POLL: poll for MCDI completion, until timeout
+ * @MCDI_MODE_EVENTS: wait for an mcdi_event. On timeout, poll once
+ * @MCDI_MODE_FAIL: we think MCDI is dead, so fail-fast all calls
+ */
enum efx_mcdi_mode {
MCDI_MODE_POLL,
MCDI_MODE_EVENTS,
+ MCDI_MODE_FAIL,
};
/**
@@ -104,6 +111,12 @@ struct efx_mcdi_data {
u32 fn_flags;
};
+static inline struct efx_mcdi_iface *efx_mcdi(struct efx_nic *efx)
+{
+ EFX_BUG_ON_PARANOID(!efx->mcdi);
+ return &efx->mcdi->iface;
+}
+
#ifdef CONFIG_SFC_MCDI_MON
static inline struct efx_mcdi_mon *efx_mcdi_mon(struct efx_nic *efx)
{
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index 8a400a0595eb..5bdae8ed7c57 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -972,6 +972,8 @@ struct efx_mtd_partition {
* (for Falcon architecture)
* @finish_flush: Clean up after flushing the DMA queues (for Falcon
* architecture)
+ * @prepare_flr: Prepare for an FLR
+ * @finish_flr: Clean up after an FLR
* @describe_stats: Describe statistics for ethtool
* @update_stats: Update statistics not provided by event handling.
* Either argument may be %NULL.
@@ -1100,6 +1102,8 @@ struct efx_nic_type {
int (*fini_dmaq)(struct efx_nic *efx);
void (*prepare_flush)(struct efx_nic *efx);
void (*finish_flush)(struct efx_nic *efx);
+ void (*prepare_flr)(struct efx_nic *efx);
+ void (*finish_flr)(struct efx_nic *efx);
size_t (*describe_stats)(struct efx_nic *efx, u8 *names);
size_t (*update_stats)(struct efx_nic *efx, u64 *full_stats,
struct rtnl_link_stats64 *core_stats);
diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c
index 32d969e857f7..89b83e59e1dc 100644
--- a/drivers/net/ethernet/sfc/nic.c
+++ b/drivers/net/ethernet/sfc/nic.c
@@ -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 */
diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h
index a001fae1a8d7..d3ad8ed8d901 100644
--- a/drivers/net/ethernet/sfc/nic.h
+++ b/drivers/net/ethernet/sfc/nic.h
@@ -757,6 +757,7 @@ static inline int efx_nic_irq_test_irq_cpu(struct efx_nic *efx)
int efx_nic_flush_queues(struct efx_nic *efx);
void siena_prepare_flush(struct efx_nic *efx);
int efx_farch_fini_dmaq(struct efx_nic *efx);
+void efx_farch_finish_flr(struct efx_nic *efx);
void siena_finish_flush(struct efx_nic *efx);
void falcon_start_nic_stats(struct efx_nic *efx);
void falcon_stop_nic_stats(struct efx_nic *efx);
diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c
index 23f3a6f7737a..50ffefed492c 100644
--- a/drivers/net/ethernet/sfc/siena.c
+++ b/drivers/net/ethernet/sfc/siena.c
@@ -921,6 +921,8 @@ const struct efx_nic_type siena_a0_nic_type = {
.fini_dmaq = efx_farch_fini_dmaq,
.prepare_flush = siena_prepare_flush,
.finish_flush = siena_finish_flush,
+ .prepare_flr = efx_port_dummy_op_void,
+ .finish_flr = efx_farch_finish_flr,
.describe_stats = siena_describe_nic_stats,
.update_stats = siena_update_nic_stats,
.start_stats = efx_mcdi_mac_start_stats,
diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c
index d1b4dca53a9d..bcaa41af1e62 100644
--- a/drivers/net/ethernet/smsc/smc91x.c
+++ b/drivers/net/ethernet/smsc/smc91x.c
@@ -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();
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index d940034acdd4..0f4841d2e8dc 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -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;
}
diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c
index df8d383acf48..b9ac20f42651 100644
--- a/drivers/net/ethernet/sun/cassini.c
+++ b/drivers/net/ethernet/sun/cassini.c
@@ -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)
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 36aa109416c4..c331b7ebc812 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -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)
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 31e55fba7cad..7918d5132c1f 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -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);
diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index 430bb0db9bc4..e36f194673a4 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -365,7 +365,7 @@ __at86rf230_read_subreg(struct at86rf230_local *lp,
dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
if (status == 0)
- *data = buf[1];
+ *data = (buf[1] & mask) >> shift;
return status;
}
@@ -1025,14 +1025,6 @@ static int at86rf230_hw_init(struct at86rf230_local *lp)
return -EINVAL;
}
- rc = at86rf230_read_subreg(lp, SR_AVDD_OK, &status);
- if (rc)
- return rc;
- if (!status) {
- dev_err(&lp->spi->dev, "AVDD error\n");
- return -EINVAL;
- }
-
return 0;
}
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 753a8c23d15d..d53e299ae1d9 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -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])
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index ff111a89e17f..3381c4f91a8c 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -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);
}
diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c
index e701433bf52f..5f1a2250018f 100644
--- a/drivers/net/phy/mdio-gpio.c
+++ b/drivers/net/phy/mdio-gpio.c
@@ -32,29 +32,39 @@
struct mdio_gpio_info {
struct mdiobb_ctrl ctrl;
- int mdc, mdio;
+ int mdc, mdio, mdo;
+ int mdc_active_low, mdio_active_low, mdo_active_low;
};
static void *mdio_gpio_of_get_data(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct mdio_gpio_platform_data *pdata;
+ enum of_gpio_flags flags;
int ret;
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return NULL;
- ret = of_get_gpio(np, 0);
+ ret = of_get_gpio_flags(np, 0, &flags);
if (ret < 0)
return NULL;
pdata->mdc = ret;
+ pdata->mdc_active_low = flags & OF_GPIO_ACTIVE_LOW;
- ret = of_get_gpio(np, 1);
+ ret = of_get_gpio_flags(np, 1, &flags);
if (ret < 0)
return NULL;
pdata->mdio = ret;
+ pdata->mdio_active_low = flags & OF_GPIO_ACTIVE_LOW;
+
+ ret = of_get_gpio_flags(np, 2, &flags);
+ if (ret > 0) {
+ pdata->mdo = ret;
+ pdata->mdo_active_low = flags & OF_GPIO_ACTIVE_LOW;
+ }
return pdata;
}
@@ -64,8 +74,19 @@ static void mdio_dir(struct mdiobb_ctrl *ctrl, int dir)
struct mdio_gpio_info *bitbang =
container_of(ctrl, struct mdio_gpio_info, ctrl);
+ if (bitbang->mdo) {
+ /* Separate output pin. Always set its value to high
+ * when changing direction. If direction is input,
+ * assume the pin serves as pull-up. If direction is
+ * output, the default value is high.
+ */
+ gpio_set_value(bitbang->mdo, 1 ^ bitbang->mdo_active_low);
+ return;
+ }
+
if (dir)
- gpio_direction_output(bitbang->mdio, 1);
+ gpio_direction_output(bitbang->mdio,
+ 1 ^ bitbang->mdio_active_low);
else
gpio_direction_input(bitbang->mdio);
}
@@ -75,7 +96,7 @@ static int mdio_get(struct mdiobb_ctrl *ctrl)
struct mdio_gpio_info *bitbang =
container_of(ctrl, struct mdio_gpio_info, ctrl);
- return gpio_get_value(bitbang->mdio);
+ return gpio_get_value(bitbang->mdio) ^ bitbang->mdio_active_low;
}
static void mdio_set(struct mdiobb_ctrl *ctrl, int what)
@@ -83,7 +104,10 @@ static void mdio_set(struct mdiobb_ctrl *ctrl, int what)
struct mdio_gpio_info *bitbang =
container_of(ctrl, struct mdio_gpio_info, ctrl);
- gpio_set_value(bitbang->mdio, what);
+ if (bitbang->mdo)
+ gpio_set_value(bitbang->mdo, what ^ bitbang->mdo_active_low);
+ else
+ gpio_set_value(bitbang->mdio, what ^ bitbang->mdio_active_low);
}
static void mdc_set(struct mdiobb_ctrl *ctrl, int what)
@@ -91,7 +115,7 @@ static void mdc_set(struct mdiobb_ctrl *ctrl, int what)
struct mdio_gpio_info *bitbang =
container_of(ctrl, struct mdio_gpio_info, ctrl);
- gpio_set_value(bitbang->mdc, what);
+ gpio_set_value(bitbang->mdc, what ^ bitbang->mdc_active_low);
}
static struct mdiobb_ops mdio_gpio_ops = {
@@ -110,18 +134,22 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev,
struct mdio_gpio_info *bitbang;
int i;
- bitbang = kzalloc(sizeof(*bitbang), GFP_KERNEL);
+ bitbang = devm_kzalloc(dev, sizeof(*bitbang), GFP_KERNEL);
if (!bitbang)
goto out;
bitbang->ctrl.ops = &mdio_gpio_ops;
bitbang->ctrl.reset = pdata->reset;
bitbang->mdc = pdata->mdc;
+ bitbang->mdc_active_low = pdata->mdc_active_low;
bitbang->mdio = pdata->mdio;
+ bitbang->mdio_active_low = pdata->mdio_active_low;
+ bitbang->mdo = pdata->mdo;
+ bitbang->mdo_active_low = pdata->mdo_active_low;
new_bus = alloc_mdio_bitbang(&bitbang->ctrl);
if (!new_bus)
- goto out_free_bitbang;
+ goto out;
new_bus->name = "GPIO Bitbanged MDIO",
@@ -138,11 +166,18 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev,
snprintf(new_bus->id, MII_BUS_ID_SIZE, "gpio-%x", bus_id);
- if (gpio_request(bitbang->mdc, "mdc"))
+ if (devm_gpio_request(dev, bitbang->mdc, "mdc"))
+ goto out_free_bus;
+
+ if (devm_gpio_request(dev, bitbang->mdio, "mdio"))
goto out_free_bus;
- if (gpio_request(bitbang->mdio, "mdio"))
- goto out_free_mdc;
+ if (bitbang->mdo) {
+ if (devm_gpio_request(dev, bitbang->mdo, "mdo"))
+ goto out_free_bus;
+ gpio_direction_output(bitbang->mdo, 1);
+ gpio_direction_input(bitbang->mdio);
+ }
gpio_direction_output(bitbang->mdc, 0);
@@ -150,12 +185,8 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev,
return new_bus;
-out_free_mdc:
- gpio_free(bitbang->mdc);
out_free_bus:
free_mdio_bitbang(new_bus);
-out_free_bitbang:
- kfree(bitbang);
out:
return NULL;
}
@@ -163,13 +194,8 @@ out:
static void mdio_gpio_bus_deinit(struct device *dev)
{
struct mii_bus *bus = dev_get_drvdata(dev);
- struct mdio_gpio_info *bitbang = bus->priv;
- dev_set_drvdata(dev, NULL);
- gpio_free(bitbang->mdio);
- gpio_free(bitbang->mdc);
free_mdio_bitbang(bus);
- kfree(bitbang);
}
static void mdio_gpio_bus_destroy(struct device *dev)
@@ -189,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;
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 5ad971a55c5d..d849684231c1 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -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);
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 1b6d09aef427..3bc079a67a3d 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -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);
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 0ce606624296..4987a1c6dc52 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -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;
}
diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c
index cc70ecfc7062..ad4a94e9ff57 100644
--- a/drivers/net/slip/slip.c
+++ b/drivers/net/slip/slip.c
@@ -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)
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 33008c1d1d67..767fe61b5ac9 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -2834,8 +2834,10 @@ static int team_device_event(struct notifier_block *unused,
case NETDEV_UP:
if (netif_carrier_ok(dev))
team_port_change_check(port, true);
+ break;
case NETDEV_DOWN:
team_port_change_check(port, false);
+ break;
case NETDEV_CHANGE:
if (netif_running(port->dev))
team_port_change_check(port,
diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c
index c9f3281506af..2e025ddcef21 100644
--- a/drivers/net/usb/cdc_mbim.c
+++ b/drivers/net/usb/cdc_mbim.c
@@ -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)
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index 549dbac710ed..9a2bd11943eb 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -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 */
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index e3458e3c44f1..83208d4fdc59 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -669,6 +669,22 @@ static const struct usb_device_id products[] = {
{QMI_FIXED_INTF(0x05c6, 0x920d, 5)},
{QMI_FIXED_INTF(0x12d1, 0x140c, 1)}, /* Huawei E173 */
{QMI_FIXED_INTF(0x12d1, 0x14ac, 1)}, /* Huawei E1820 */
+ {QMI_FIXED_INTF(0x16d8, 0x6003, 0)}, /* CMOTech 6003 */
+ {QMI_FIXED_INTF(0x16d8, 0x6007, 0)}, /* CMOTech CHE-628S */
+ {QMI_FIXED_INTF(0x16d8, 0x6008, 0)}, /* CMOTech CMU-301 */
+ {QMI_FIXED_INTF(0x16d8, 0x6280, 0)}, /* CMOTech CHU-628 */
+ {QMI_FIXED_INTF(0x16d8, 0x7001, 0)}, /* CMOTech CHU-720S */
+ {QMI_FIXED_INTF(0x16d8, 0x7002, 0)}, /* CMOTech 7002 */
+ {QMI_FIXED_INTF(0x16d8, 0x7003, 4)}, /* CMOTech CHU-629K */
+ {QMI_FIXED_INTF(0x16d8, 0x7004, 3)}, /* CMOTech 7004 */
+ {QMI_FIXED_INTF(0x16d8, 0x7006, 5)}, /* CMOTech CGU-629 */
+ {QMI_FIXED_INTF(0x16d8, 0x700a, 4)}, /* CMOTech CHU-629S */
+ {QMI_FIXED_INTF(0x16d8, 0x7211, 0)}, /* CMOTech CHU-720I */
+ {QMI_FIXED_INTF(0x16d8, 0x7212, 0)}, /* CMOTech 7212 */
+ {QMI_FIXED_INTF(0x16d8, 0x7213, 0)}, /* CMOTech 7213 */
+ {QMI_FIXED_INTF(0x16d8, 0x7251, 1)}, /* CMOTech 7251 */
+ {QMI_FIXED_INTF(0x16d8, 0x7252, 1)}, /* CMOTech 7252 */
+ {QMI_FIXED_INTF(0x16d8, 0x7253, 1)}, /* CMOTech 7253 */
{QMI_FIXED_INTF(0x19d2, 0x0002, 1)},
{QMI_FIXED_INTF(0x19d2, 0x0012, 1)},
{QMI_FIXED_INTF(0x19d2, 0x0017, 3)},
@@ -730,16 +746,28 @@ static const struct usb_device_id products[] = {
{QMI_FIXED_INTF(0x114f, 0x68a2, 8)}, /* Sierra Wireless MC7750 */
{QMI_FIXED_INTF(0x1199, 0x68a2, 8)}, /* Sierra Wireless MC7710 in QMI mode */
{QMI_FIXED_INTF(0x1199, 0x68a2, 19)}, /* Sierra Wireless MC7710 in QMI mode */
+ {QMI_FIXED_INTF(0x1199, 0x68c0, 8)}, /* Sierra Wireless MC73xx */
+ {QMI_FIXED_INTF(0x1199, 0x68c0, 10)}, /* Sierra Wireless MC73xx */
+ {QMI_FIXED_INTF(0x1199, 0x68c0, 11)}, /* Sierra Wireless MC73xx */
{QMI_FIXED_INTF(0x1199, 0x901c, 8)}, /* Sierra Wireless EM7700 */
+ {QMI_FIXED_INTF(0x1199, 0x901f, 8)}, /* Sierra Wireless EM7355 */
+ {QMI_FIXED_INTF(0x1199, 0x9041, 8)}, /* Sierra Wireless MC7305/MC7355 */
{QMI_FIXED_INTF(0x1199, 0x9051, 8)}, /* Netgear AirCard 340U */
{QMI_FIXED_INTF(0x1bbb, 0x011e, 4)}, /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */
+ {QMI_FIXED_INTF(0x1bbb, 0x0203, 2)}, /* Alcatel L800MA */
{QMI_FIXED_INTF(0x2357, 0x0201, 4)}, /* TP-LINK HSUPA Modem MA180 */
{QMI_FIXED_INTF(0x2357, 0x9000, 4)}, /* TP-LINK MA260 */
{QMI_FIXED_INTF(0x1bc7, 0x1200, 5)}, /* Telit LE920 */
{QMI_FIXED_INTF(0x1bc7, 0x1201, 2)}, /* Telit LE920 */
{QMI_FIXED_INTF(0x0b3c, 0xc005, 6)}, /* Olivetti Olicard 200 */
+ {QMI_FIXED_INTF(0x0b3c, 0xc00b, 4)}, /* Olivetti Olicard 500 */
{QMI_FIXED_INTF(0x1e2d, 0x0060, 4)}, /* Cinterion PLxx */
{QMI_FIXED_INTF(0x1e2d, 0x0053, 4)}, /* Cinterion PHxx,PXxx */
+ {QMI_FIXED_INTF(0x413c, 0x81a2, 8)}, /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card */
+ {QMI_FIXED_INTF(0x413c, 0x81a3, 8)}, /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card */
+ {QMI_FIXED_INTF(0x413c, 0x81a4, 8)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */
+ {QMI_FIXED_INTF(0x413c, 0x81a8, 8)}, /* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card */
+ {QMI_FIXED_INTF(0x413c, 0x81a9, 8)}, /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */
/* 4. Gobi 1000 devices */
{QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 7b687469199b..8a852b5f215f 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -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();
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index c55e316373a1..4dbb2ed85b97 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -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);
@@ -1755,8 +1759,8 @@ int vxlan_xmit_skb(struct vxlan_sock *vs,
if (err)
return err;
- return iptunnel_xmit(rt, skb, src, dst, IPPROTO_UDP, tos, ttl, df,
- false);
+ return iptunnel_xmit(vs->sock->sk, rt, skb, src, dst, IPPROTO_UDP,
+ tos, ttl, df, false);
}
EXPORT_SYMBOL_GPL(vxlan_xmit_skb);
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index 84734a805092..83c39e2858bf 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -1521,11 +1521,7 @@ static int cosa_reset_and_read_id(struct cosa_data *cosa, char *idstring)
cosa_putstatus(cosa, 0);
cosa_getdata8(cosa);
cosa_putstatus(cosa, SR_RST);
-#ifdef MODULE
msleep(500);
-#else
- udelay(5*100000);
-#endif
/* Disable all IRQs from the card */
cosa_putstatus(cosa, 0);
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
index a0398fe3eb28..be3eb2a8d602 100644
--- a/drivers/net/wireless/ath/ath9k/ahb.c
+++ b/drivers/net/wireless/ath/ath9k/ahb.c
@@ -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:
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c
index 6d47783f2e5b..ba502a2d199b 100644
--- a/drivers/net/wireless/ath/ath9k/ani.c
+++ b/drivers/net/wireless/ath/ath9k/ani.c
@@ -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)
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 44d74495c4de..3ba03dde4215 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -251,7 +251,6 @@ struct ath_atx_tid {
s8 bar_index;
bool sched;
- bool paused;
bool active;
};
diff --git a/drivers/net/wireless/ath/ath9k/debug_sta.c b/drivers/net/wireless/ath/ath9k/debug_sta.c
index d76e6e0120d2..ffca918ff16a 100644
--- a/drivers/net/wireless/ath/ath9k/debug_sta.c
+++ b/drivers/net/wireless/ath/ath9k/debug_sta.c
@@ -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);
}
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index f46cd0250e48..5627917c5ff7 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -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);
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index cbbb02a6b13b..36ae6490e554 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -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);
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index 25304adece57..914dbc6b1720 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -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:
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 6c9accdb52e4..19df969ec909 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -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)) {
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 87cbec47fb48..66acb2cbd9df 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -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);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/brcm80211/brcmfmac/chip.c
index df130ef53d1c..c7c9f15c0fe0 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c
@@ -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);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index afb3d15e38ff..be1985296bdc 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -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 {
diff --git a/drivers/net/wireless/cw1200/debug.c b/drivers/net/wireless/cw1200/debug.c
index e323b4d54338..34f97c31eecf 100644
--- a/drivers/net/wireless/cw1200/debug.c
+++ b/drivers/net/wireless/cw1200/debug.c
@@ -41,6 +41,8 @@ static const char * const cw1200_debug_link_id[] = {
"REQ",
"SOFT",
"HARD",
+ "RESET",
+ "RESET_REMAP",
};
static const char *cw1200_debug_mode(int mode)
diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c
index 003a546571d4..4c2d4ef28b22 100644
--- a/drivers/net/wireless/iwlwifi/iwl-7000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-7000.c
@@ -67,8 +67,8 @@
#include "iwl-agn-hw.h"
/* Highest firmware API version supported */
-#define IWL7260_UCODE_API_MAX 8
-#define IWL3160_UCODE_API_MAX 8
+#define IWL7260_UCODE_API_MAX 9
+#define IWL3160_UCODE_API_MAX 9
/* Oldest version we won't warn about */
#define IWL7260_UCODE_API_OK 8
@@ -244,3 +244,4 @@ const struct iwl_cfg iwl7265_n_cfg = {
MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK));
+MODULE_FIRMWARE(IWL7265_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
diff --git a/drivers/net/wireless/iwlwifi/mvm/coex.c b/drivers/net/wireless/iwlwifi/mvm/coex.c
index 685f7e8e6943..0489314425cb 100644
--- a/drivers/net/wireless/iwlwifi/mvm/coex.c
+++ b/drivers/net/wireless/iwlwifi/mvm/coex.c
@@ -190,7 +190,7 @@ static const __le32 iwl_combined_lookup[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = {
cpu_to_le32(0xcc00aaaa),
cpu_to_le32(0x0000aaaa),
cpu_to_le32(0xc0004000),
- cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00004000),
cpu_to_le32(0xf0005000),
cpu_to_le32(0xf0005000),
},
@@ -213,16 +213,16 @@ static const __le32 iwl_combined_lookup[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = {
/* Tx Tx disabled */
cpu_to_le32(0xaaaaaaaa),
cpu_to_le32(0xaaaaaaaa),
- cpu_to_le32(0xaaaaaaaa),
+ cpu_to_le32(0xeeaaaaaa),
cpu_to_le32(0xaaaaaaaa),
cpu_to_le32(0xcc00ff28),
cpu_to_le32(0x0000aaaa),
cpu_to_le32(0xcc00aaaa),
cpu_to_le32(0x0000aaaa),
- cpu_to_le32(0xC0004000),
- cpu_to_le32(0xC0004000),
- cpu_to_le32(0xF0005000),
- cpu_to_le32(0xF0005000),
+ cpu_to_le32(0xc0004000),
+ cpu_to_le32(0xc0004000),
+ cpu_to_le32(0xf0005000),
+ cpu_to_le32(0xf0005000),
},
};
@@ -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)
@@ -1262,6 +1262,7 @@ int iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm,
struct iwl_rx_packet *pkt = rxb_addr(rxb);
u32 ant_isolation = le32_to_cpup((void *)pkt->data);
u8 __maybe_unused lower_bound, upper_bound;
+ int ret;
u8 lut;
struct iwl_bt_coex_cmd *bt_cmd;
@@ -1318,5 +1319,8 @@ int iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm,
memcpy(bt_cmd->bt4_corun_lut40, antenna_coupling_ranges[lut].lut20,
sizeof(bt_cmd->bt4_corun_lut40));
- return 0;
+ ret = iwl_mvm_send_cmd(mvm, &cmd);
+
+ kfree(bt_cmd);
+ return ret;
}
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
index 9426905de6b2..d73a89ecd78a 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
@@ -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.
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index 4dd9ff43b8b6..b41dc84e9431 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -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);
}
@@ -1332,6 +1332,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
*/
iwl_mvm_remove_time_event(mvm, mvmvif,
&mvmvif->time_event_data);
+ iwl_mvm_sf_update(mvm, vif, false);
WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, CMD_SYNC));
} else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS |
BSS_CHANGED_QOS)) {
@@ -1806,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");
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index d564233a65da..f1ec0986c3c9 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -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);
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c
index 568abd61b14f..e1c838899363 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.c
@@ -59,7 +59,7 @@
/* max allowed rate miss before sync LQ cmd */
#define IWL_MISSED_RATE_MAX 15
#define RS_STAY_IN_COLUMN_TIMEOUT (5*HZ)
-
+#define RS_IDLE_TIMEOUT (5*HZ)
static u8 rs_ht_to_legacy[] = {
[IWL_RATE_MCS_0_INDEX] = IWL_RATE_6M_INDEX,
@@ -142,7 +142,7 @@ enum rs_column_mode {
RS_MIMO2,
};
-#define MAX_NEXT_COLUMNS 5
+#define MAX_NEXT_COLUMNS 7
#define MAX_COLUMN_CHECKS 3
typedef bool (*allow_column_func_t) (struct iwl_mvm *mvm,
@@ -212,8 +212,10 @@ static const struct rs_tx_column rs_tx_columns[] = {
RS_COLUMN_LEGACY_ANT_B,
RS_COLUMN_SISO_ANT_A,
RS_COLUMN_SISO_ANT_B,
- RS_COLUMN_MIMO2,
- RS_COLUMN_MIMO2_SGI,
+ RS_COLUMN_INVALID,
+ RS_COLUMN_INVALID,
+ RS_COLUMN_INVALID,
+ RS_COLUMN_INVALID,
},
},
[RS_COLUMN_LEGACY_ANT_B] = {
@@ -223,8 +225,10 @@ static const struct rs_tx_column rs_tx_columns[] = {
RS_COLUMN_LEGACY_ANT_A,
RS_COLUMN_SISO_ANT_A,
RS_COLUMN_SISO_ANT_B,
- RS_COLUMN_MIMO2,
- RS_COLUMN_MIMO2_SGI,
+ RS_COLUMN_INVALID,
+ RS_COLUMN_INVALID,
+ RS_COLUMN_INVALID,
+ RS_COLUMN_INVALID,
},
},
[RS_COLUMN_SISO_ANT_A] = {
@@ -235,7 +239,9 @@ static const struct rs_tx_column rs_tx_columns[] = {
RS_COLUMN_MIMO2,
RS_COLUMN_SISO_ANT_A_SGI,
RS_COLUMN_SISO_ANT_B_SGI,
- RS_COLUMN_MIMO2_SGI,
+ RS_COLUMN_LEGACY_ANT_A,
+ RS_COLUMN_LEGACY_ANT_B,
+ RS_COLUMN_INVALID,
},
.checks = {
rs_siso_allow,
@@ -249,7 +255,9 @@ static const struct rs_tx_column rs_tx_columns[] = {
RS_COLUMN_MIMO2,
RS_COLUMN_SISO_ANT_B_SGI,
RS_COLUMN_SISO_ANT_A_SGI,
- RS_COLUMN_MIMO2_SGI,
+ RS_COLUMN_LEGACY_ANT_A,
+ RS_COLUMN_LEGACY_ANT_B,
+ RS_COLUMN_INVALID,
},
.checks = {
rs_siso_allow,
@@ -265,6 +273,8 @@ static const struct rs_tx_column rs_tx_columns[] = {
RS_COLUMN_SISO_ANT_A,
RS_COLUMN_SISO_ANT_B,
RS_COLUMN_MIMO2,
+ RS_COLUMN_LEGACY_ANT_A,
+ RS_COLUMN_LEGACY_ANT_B,
},
.checks = {
rs_siso_allow,
@@ -281,6 +291,8 @@ static const struct rs_tx_column rs_tx_columns[] = {
RS_COLUMN_SISO_ANT_B,
RS_COLUMN_SISO_ANT_A,
RS_COLUMN_MIMO2,
+ RS_COLUMN_LEGACY_ANT_A,
+ RS_COLUMN_LEGACY_ANT_B,
},
.checks = {
rs_siso_allow,
@@ -296,6 +308,8 @@ static const struct rs_tx_column rs_tx_columns[] = {
RS_COLUMN_SISO_ANT_A_SGI,
RS_COLUMN_SISO_ANT_B_SGI,
RS_COLUMN_MIMO2_SGI,
+ RS_COLUMN_LEGACY_ANT_A,
+ RS_COLUMN_LEGACY_ANT_B,
},
.checks = {
rs_mimo_allow,
@@ -311,6 +325,8 @@ static const struct rs_tx_column rs_tx_columns[] = {
RS_COLUMN_SISO_ANT_A,
RS_COLUMN_SISO_ANT_B,
RS_COLUMN_MIMO2,
+ RS_COLUMN_LEGACY_ANT_A,
+ RS_COLUMN_LEGACY_ANT_B,
},
.checks = {
rs_mimo_allow,
@@ -503,10 +519,12 @@ static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window)
window->average_tpt = IWL_INVALID_VALUE;
}
-static void rs_rate_scale_clear_tbl_windows(struct iwl_scale_tbl_info *tbl)
+static void rs_rate_scale_clear_tbl_windows(struct iwl_mvm *mvm,
+ struct iwl_scale_tbl_info *tbl)
{
int i;
+ IWL_DEBUG_RATE(mvm, "Clearing up window stats\n");
for (i = 0; i < IWL_RATE_COUNT; i++)
rs_rate_scale_clear_window(&tbl->win[i]);
}
@@ -992,6 +1010,13 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband,
return;
}
+#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");
+ return;
+ }
+#endif
if (!ieee80211_is_data(hdr->frame_control) ||
info->flags & IEEE80211_TX_CTL_NO_ACK)
return;
@@ -1034,6 +1059,18 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband,
mac_index++;
}
+ if (time_after(jiffies,
+ (unsigned long)(lq_sta->last_tx + RS_IDLE_TIMEOUT))) {
+ int tid;
+ IWL_DEBUG_RATE(mvm, "Tx idle for too long. reinit rs\n");
+ for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++)
+ ieee80211_stop_tx_ba_session(sta, tid);
+
+ iwl_mvm_rs_rate_init(mvm, sta, sband->band, false);
+ return;
+ }
+ lq_sta->last_tx = jiffies;
+
/* Here we actually compare this rate to the latest LQ command */
if ((mac_index < 0) ||
(rate.sgi != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) ||
@@ -1186,9 +1223,26 @@ static void rs_set_stay_in_table(struct iwl_mvm *mvm, u8 is_legacy,
lq_sta->visited_columns = 0;
}
+static int rs_get_max_allowed_rate(struct iwl_lq_sta *lq_sta,
+ const struct rs_tx_column *column)
+{
+ switch (column->mode) {
+ case RS_LEGACY:
+ return lq_sta->max_legacy_rate_idx;
+ case RS_SISO:
+ return lq_sta->max_siso_rate_idx;
+ case RS_MIMO2:
+ return lq_sta->max_mimo2_rate_idx;
+ default:
+ WARN_ON_ONCE(1);
+ }
+
+ return lq_sta->max_legacy_rate_idx;
+}
+
static const u16 *rs_get_expected_tpt_table(struct iwl_lq_sta *lq_sta,
- const struct rs_tx_column *column,
- u32 bw)
+ const struct rs_tx_column *column,
+ u32 bw)
{
/* Used to choose among HT tables */
const u16 (*ht_tbl_pointer)[IWL_RATE_COUNT];
@@ -1438,7 +1492,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search)
IWL_DEBUG_RATE(mvm,
"LQ: stay in table clear win\n");
- rs_rate_scale_clear_tbl_windows(tbl);
+ rs_rate_scale_clear_tbl_windows(mvm, tbl);
}
}
@@ -1446,8 +1500,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search)
* bitmaps and stats in active table (this will become the new
* "search" table). */
if (lq_sta->rs_state == RS_STATE_SEARCH_CYCLE_STARTED) {
- IWL_DEBUG_RATE(mvm, "Clearing up window stats\n");
- rs_rate_scale_clear_tbl_windows(tbl);
+ rs_rate_scale_clear_tbl_windows(mvm, tbl);
}
}
}
@@ -1485,14 +1538,14 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
struct iwl_scale_tbl_info *tbl)
{
- int i, j, n;
+ int i, j, max_rate;
enum rs_column next_col_id;
const struct rs_tx_column *curr_col = &rs_tx_columns[tbl->column];
const struct rs_tx_column *next_col;
allow_column_func_t allow_func;
u8 valid_ants = mvm->fw->valid_tx_ant;
const u16 *expected_tpt_tbl;
- s32 tpt, max_expected_tpt;
+ u16 tpt, max_expected_tpt;
for (i = 0; i < MAX_NEXT_COLUMNS; i++) {
next_col_id = curr_col->next_columns[i];
@@ -1535,11 +1588,11 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm,
if (WARN_ON_ONCE(!expected_tpt_tbl))
continue;
- max_expected_tpt = 0;
- for (n = 0; n < IWL_RATE_COUNT; n++)
- if (expected_tpt_tbl[n] > max_expected_tpt)
- max_expected_tpt = expected_tpt_tbl[n];
+ max_rate = rs_get_max_allowed_rate(lq_sta, next_col);
+ if (WARN_ON_ONCE(max_rate == IWL_RATE_INVALID))
+ continue;
+ max_expected_tpt = expected_tpt_tbl[max_rate];
if (tpt >= max_expected_tpt) {
IWL_DEBUG_RATE(mvm,
"Skip column %d: can't beat current TPT. Max expected %d current %d\n",
@@ -1547,14 +1600,15 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm,
continue;
}
+ IWL_DEBUG_RATE(mvm,
+ "Found potential column %d. Max expected %d current %d\n",
+ next_col_id, max_expected_tpt, tpt);
break;
}
if (i == MAX_NEXT_COLUMNS)
return RS_COLUMN_INVALID;
- IWL_DEBUG_RATE(mvm, "Found potential column %d\n", next_col_id);
-
return next_col_id;
}
@@ -1640,85 +1694,76 @@ static enum rs_action rs_get_rate_action(struct iwl_mvm *mvm,
{
enum rs_action action = RS_ACTION_STAY;
- /* Too many failures, decrease rate */
if ((sr <= RS_SR_FORCE_DECREASE) || (current_tpt == 0)) {
IWL_DEBUG_RATE(mvm,
- "decrease rate because of low SR\n");
- action = RS_ACTION_DOWNSCALE;
- /* No throughput measured yet for adjacent rates; try increase. */
- } else if ((low_tpt == IWL_INVALID_VALUE) &&
- (high_tpt == IWL_INVALID_VALUE)) {
- if (high != IWL_RATE_INVALID && sr >= IWL_RATE_INCREASE_TH) {
- IWL_DEBUG_RATE(mvm,
- "Good SR and no high rate measurement. "
- "Increase rate\n");
- action = RS_ACTION_UPSCALE;
- } else if (low != IWL_RATE_INVALID) {
- IWL_DEBUG_RATE(mvm,
- "Remain in current rate\n");
- action = RS_ACTION_STAY;
- }
+ "Decrease rate because of low SR\n");
+ return RS_ACTION_DOWNSCALE;
}
- /* Both adjacent throughputs are measured, but neither one has better
- * throughput; we're using the best rate, don't change it!
- */
- else if ((low_tpt != IWL_INVALID_VALUE) &&
- (high_tpt != IWL_INVALID_VALUE) &&
- (low_tpt < current_tpt) &&
- (high_tpt < current_tpt)) {
+ if ((low_tpt == IWL_INVALID_VALUE) &&
+ (high_tpt == IWL_INVALID_VALUE) &&
+ (high != IWL_RATE_INVALID)) {
IWL_DEBUG_RATE(mvm,
- "Both high and low are worse. "
- "Maintain rate\n");
- action = RS_ACTION_STAY;
+ "No data about high/low rates. Increase rate\n");
+ return RS_ACTION_UPSCALE;
}
- /* At least one adjacent rate's throughput is measured,
- * and may have better performance.
- */
- else {
- /* Higher adjacent rate's throughput is measured */
- if (high_tpt != IWL_INVALID_VALUE) {
- /* Higher rate has better throughput */
- if (high_tpt > current_tpt &&
- sr >= IWL_RATE_INCREASE_TH) {
- IWL_DEBUG_RATE(mvm,
- "Higher rate is better and good "
- "SR. Increate rate\n");
- action = RS_ACTION_UPSCALE;
- } else {
- IWL_DEBUG_RATE(mvm,
- "Higher rate isn't better OR "
- "no good SR. Maintain rate\n");
- action = RS_ACTION_STAY;
- }
+ if ((high_tpt == IWL_INVALID_VALUE) &&
+ (high != IWL_RATE_INVALID) &&
+ (low_tpt != IWL_INVALID_VALUE) &&
+ (low_tpt < current_tpt)) {
+ IWL_DEBUG_RATE(mvm,
+ "No data about high rate and low rate is worse. Increase rate\n");
+ return RS_ACTION_UPSCALE;
+ }
- /* Lower adjacent rate's throughput is measured */
- } else if (low_tpt != IWL_INVALID_VALUE) {
- /* Lower rate has better throughput */
- if (low_tpt > current_tpt) {
- IWL_DEBUG_RATE(mvm,
- "Lower rate is better. "
- "Decrease rate\n");
- action = RS_ACTION_DOWNSCALE;
- } else if (sr >= IWL_RATE_INCREASE_TH) {
- IWL_DEBUG_RATE(mvm,
- "Lower rate isn't better and "
- "good SR. Increase rate\n");
- action = RS_ACTION_UPSCALE;
- }
- }
+ if ((high_tpt != IWL_INVALID_VALUE) &&
+ (high_tpt > current_tpt)) {
+ IWL_DEBUG_RATE(mvm,
+ "Higher rate is better. Increate rate\n");
+ return RS_ACTION_UPSCALE;
}
- /* Sanity check; asked for decrease, but success rate or throughput
- * has been good at old rate. Don't change it.
- */
- if ((action == RS_ACTION_DOWNSCALE) && (low != IWL_RATE_INVALID) &&
- ((sr > IWL_RATE_HIGH_TH) ||
- (current_tpt > (100 * tbl->expected_tpt[low])))) {
+ if ((low_tpt != IWL_INVALID_VALUE) &&
+ (high_tpt != IWL_INVALID_VALUE) &&
+ (low_tpt < current_tpt) &&
+ (high_tpt < current_tpt)) {
+ IWL_DEBUG_RATE(mvm,
+ "Both high and low are worse. Maintain rate\n");
+ return RS_ACTION_STAY;
+ }
+
+ if ((low_tpt != IWL_INVALID_VALUE) &&
+ (low_tpt > current_tpt)) {
+ IWL_DEBUG_RATE(mvm,
+ "Lower rate is better\n");
+ action = RS_ACTION_DOWNSCALE;
+ goto out;
+ }
+
+ if ((low_tpt == IWL_INVALID_VALUE) &&
+ (low != IWL_RATE_INVALID)) {
IWL_DEBUG_RATE(mvm,
- "Sanity check failed. Maintain rate\n");
- action = RS_ACTION_STAY;
+ "No data about lower rate\n");
+ action = RS_ACTION_DOWNSCALE;
+ goto out;
+ }
+
+ IWL_DEBUG_RATE(mvm, "Maintain rate\n");
+
+out:
+ if ((action == RS_ACTION_DOWNSCALE) && (low != IWL_RATE_INVALID)) {
+ if (sr >= RS_SR_NO_DECREASE) {
+ IWL_DEBUG_RATE(mvm,
+ "SR is above NO DECREASE. Avoid downscale\n");
+ action = RS_ACTION_STAY;
+ } else if (current_tpt > (100 * tbl->expected_tpt[low])) {
+ IWL_DEBUG_RATE(mvm,
+ "Current TPT is higher than max expected in low rate. Avoid downscale\n");
+ action = RS_ACTION_STAY;
+ } else {
+ IWL_DEBUG_RATE(mvm, "Decrease rate\n");
+ }
}
return action;
@@ -1792,6 +1837,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
"Aggregation changed: prev %d current %d. Update expected TPT table\n",
prev_agg, lq_sta->is_agg);
rs_set_expected_tpt_table(lq_sta, tbl);
+ rs_rate_scale_clear_tbl_windows(mvm, tbl);
}
/* current tx rate */
@@ -2021,7 +2067,7 @@ lq_update:
if (lq_sta->search_better_tbl) {
/* Access the "search" table, clear its history. */
tbl = &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
- rs_rate_scale_clear_tbl_windows(tbl);
+ rs_rate_scale_clear_tbl_windows(mvm, tbl);
/* Use new "search" start rate */
index = tbl->rate.index;
@@ -2042,8 +2088,18 @@ lq_update:
* stay with best antenna legacy modulation for a while
* before next round of mode comparisons. */
tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]);
- if (is_legacy(&tbl1->rate) && !sta->ht_cap.ht_supported) {
+ if (is_legacy(&tbl1->rate)) {
IWL_DEBUG_RATE(mvm, "LQ: STAY in legacy table\n");
+
+ if (tid != IWL_MAX_TID_COUNT) {
+ tid_data = &sta_priv->tid_data[tid];
+ if (tid_data->state != IWL_AGG_OFF) {
+ IWL_DEBUG_RATE(mvm,
+ "Stop aggregation on tid %d\n",
+ tid);
+ ieee80211_stop_tx_ba_session(sta, tid);
+ }
+ }
rs_set_stay_in_table(mvm, 1, lq_sta);
} else {
/* If we're in an HT mode, and all 3 mode switch actions
@@ -2342,9 +2398,10 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
lq_sta->lq.sta_id = sta_priv->sta_id;
for (j = 0; j < LQ_SIZE; j++)
- rs_rate_scale_clear_tbl_windows(&lq_sta->lq_info[j]);
+ rs_rate_scale_clear_tbl_windows(mvm, &lq_sta->lq_info[j]);
lq_sta->flush_timer = 0;
+ lq_sta->last_tx = jiffies;
IWL_DEBUG_RATE(mvm,
"LQ: *** rate scale station global init for station %d ***\n",
@@ -2388,11 +2445,22 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
lq_sta->is_vht = true;
}
- IWL_DEBUG_RATE(mvm,
- "SISO-RATE=%X MIMO2-RATE=%X VHT=%d\n",
+ lq_sta->max_legacy_rate_idx = find_last_bit(&lq_sta->active_legacy_rate,
+ BITS_PER_LONG);
+ lq_sta->max_siso_rate_idx = find_last_bit(&lq_sta->active_siso_rate,
+ BITS_PER_LONG);
+ lq_sta->max_mimo2_rate_idx = find_last_bit(&lq_sta->active_mimo2_rate,
+ BITS_PER_LONG);
+
+ IWL_DEBUG_RATE(mvm, "RATE MASK: LEGACY=%lX SISO=%lX MIMO2=%lX VHT=%d\n",
+ lq_sta->active_legacy_rate,
lq_sta->active_siso_rate,
lq_sta->active_mimo2_rate,
lq_sta->is_vht);
+ IWL_DEBUG_RATE(mvm, "MAX RATE: LEGACY=%d SISO=%d MIMO2=%d\n",
+ lq_sta->max_legacy_rate_idx,
+ lq_sta->max_siso_rate_idx,
+ lq_sta->max_mimo2_rate_idx);
/* These values will be overridden later */
lq_sta->lq.single_stream_ant_msk =
@@ -2547,6 +2615,7 @@ static void rs_build_rates_table(struct iwl_mvm *mvm,
if (is_siso(&rate)) {
num_rates = RS_SECONDARY_SISO_NUM_RATES;
num_retries = RS_SECONDARY_SISO_RETRIES;
+ lq_cmd->mimo_delim = index;
} else if (is_legacy(&rate)) {
num_rates = RS_SECONDARY_LEGACY_NUM_RATES;
num_retries = RS_LEGACY_RETRIES_PER_RATE;
@@ -2749,7 +2818,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
return -ENOMEM;
desc += sprintf(buff+desc, "sta_id %d\n", lq_sta->lq.sta_id);
- desc += sprintf(buff+desc, "failed=%d success=%d rate=0%X\n",
+ desc += sprintf(buff+desc, "failed=%d success=%d rate=0%lX\n",
lq_sta->total_failed, lq_sta->total_success,
lq_sta->active_legacy_rate);
desc += sprintf(buff+desc, "fixed rate 0x%X\n",
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h
index 3332b396011e..0acfac96a56c 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.h
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.h
@@ -156,6 +156,7 @@ enum {
#define IWL_RATE_HIGH_TH 10880 /* 85% */
#define IWL_RATE_INCREASE_TH 6400 /* 50% */
#define RS_SR_FORCE_DECREASE 1920 /* 15% */
+#define RS_SR_NO_DECREASE 10880 /* 85% */
#define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) /* 4 milliseconds */
#define LINK_QUAL_AGG_TIME_LIMIT_MAX (8000)
@@ -310,13 +311,20 @@ struct iwl_lq_sta {
u32 visited_columns; /* Bitmask marking which Tx columns were
* explored during a search cycle
*/
+ u64 last_tx;
bool is_vht;
enum ieee80211_band band;
/* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */
- u16 active_legacy_rate;
- u16 active_siso_rate;
- u16 active_mimo2_rate;
+ unsigned long active_legacy_rate;
+ unsigned long active_siso_rate;
+ unsigned long active_mimo2_rate;
+
+ /* Highest rate per Tx mode */
+ u8 max_legacy_rate_idx;
+ u8 max_siso_rate_idx;
+ u8 max_mimo2_rate_idx;
+
s8 max_rate_idx; /* Max rate set by user */
u8 missed_rate_counter;
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c
index c91dc8498852..c28de54c75d4 100644
--- a/drivers/net/wireless/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/iwlwifi/mvm/scan.c
@@ -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;
diff --git a/drivers/net/wireless/iwlwifi/mvm/sf.c b/drivers/net/wireless/iwlwifi/mvm/sf.c
index 8401627c0030..88809b2d1654 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sf.c
+++ b/drivers/net/wireless/iwlwifi/mvm/sf.c
@@ -274,7 +274,8 @@ int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *changed_vif,
return -EINVAL;
if (changed_vif->type != NL80211_IFTYPE_STATION) {
new_state = SF_UNINIT;
- } else if (changed_vif->bss_conf.assoc) {
+ } else if (changed_vif->bss_conf.assoc &&
+ changed_vif->bss_conf.dtim_period) {
mvmvif = iwl_mvm_vif_from_mac80211(changed_vif);
sta_id = mvmvif->ap_sta_id;
new_state = SF_FULL_ON;
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c
index d619851745a1..2180902266ae 100644
--- a/drivers/net/wireless/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/iwlwifi/mvm/utils.c
@@ -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;
+}
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c
index edb015c99049..3d1d57f9f5bc 100644
--- a/drivers/net/wireless/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/iwlwifi/pcie/drv.c
@@ -373,12 +373,14 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
{IWL_PCI_DEVICE(0x095A, 0x500A, iwl7265_2n_cfg)},
{IWL_PCI_DEVICE(0x095B, 0x5200, iwl7265_2n_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x5002, iwl7265_n_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x5102, iwl7265_n_cfg)},
{IWL_PCI_DEVICE(0x095B, 0x5202, iwl7265_n_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x9010, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x9012, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x9110, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x9112, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x9210, iwl7265_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x9200, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x9510, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x9310, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x9410, iwl7265_2ac_cfg)},
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index dcfd6d866d09..2365553f1ef7 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -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:
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index 77db0886c6e2..9c771b3e9918 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -292,6 +292,12 @@ process_start:
while ((skb = skb_dequeue(&adapter->usb_rx_data_q)))
mwifiex_handle_rx_packet(adapter, skb);
+ /* Check for event */
+ if (adapter->event_received) {
+ adapter->event_received = false;
+ mwifiex_process_event(adapter);
+ }
+
/* Check for Cmd Resp */
if (adapter->cmd_resp_received) {
adapter->cmd_resp_received = false;
@@ -304,12 +310,6 @@ process_start:
}
}
- /* Check for event */
- if (adapter->event_received) {
- adapter->event_received = false;
- mwifiex_process_event(adapter);
- }
-
/* Check if we need to confirm Sleep Request
received previously */
if (adapter->ps_state == PS_STATE_PRE_SLEEP) {
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index 894270611f2c..536c14aa71f3 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -60,9 +60,10 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter,
int status;
/* Wait for completion */
- status = wait_event_interruptible(adapter->cmd_wait_q.wait,
- *(cmd_queued->condition));
- if (status) {
+ status = wait_event_interruptible_timeout(adapter->cmd_wait_q.wait,
+ *(cmd_queued->condition),
+ (12 * HZ));
+ if (status <= 0) {
dev_err(adapter->dev, "cmd_wait_q terminated: %d\n", status);
mwifiex_cancel_all_pending_cmd(adapter);
return status;
diff --git a/drivers/net/wireless/rsi/rsi_91x_core.c b/drivers/net/wireless/rsi/rsi_91x_core.c
index 1a8d32138593..cf61d6e3eaa7 100644
--- a/drivers/net/wireless/rsi/rsi_91x_core.c
+++ b/drivers/net/wireless/rsi/rsi_91x_core.c
@@ -88,7 +88,7 @@ static u8 rsi_core_determine_hal_queue(struct rsi_common *common)
bool recontend_queue = false;
u32 q_len = 0;
u8 q_num = INVALID_QUEUE;
- u8 ii, min = 0;
+ u8 ii = 0, min = 0;
if (skb_queue_len(&common->tx_queue[MGMT_SOFT_Q])) {
if (!common->mgmt_q_block)
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
index 73694295648f..1b28cda6ca88 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -841,16 +841,6 @@ int rsi_set_channel(struct rsi_common *common, u16 channel)
rsi_dbg(MGMT_TX_ZONE,
"%s: Sending scan req frame\n", __func__);
- skb = dev_alloc_skb(FRAME_DESC_SZ);
- if (!skb) {
- rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
- __func__);
- return -ENOMEM;
- }
-
- memset(skb->data, 0, FRAME_DESC_SZ);
- mgmt_frame = (struct rsi_mac_frame *)skb->data;
-
if (common->band == IEEE80211_BAND_5GHZ) {
if ((channel >= 36) && (channel <= 64))
channel = ((channel - 32) / 4);
@@ -868,6 +858,16 @@ int rsi_set_channel(struct rsi_common *common, u16 channel)
}
}
+ skb = dev_alloc_skb(FRAME_DESC_SZ);
+ if (!skb) {
+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ memset(skb->data, 0, FRAME_DESC_SZ);
+ mgmt_frame = (struct rsi_mac_frame *)skb->data;
+
mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);
mgmt_frame->desc_word[1] = cpu_to_le16(SCAN_REQUEST);
mgmt_frame->desc_word[4] = cpu_to_le16(channel);
@@ -966,6 +966,7 @@ static int rsi_send_auto_rate_request(struct rsi_common *common)
if (!selected_rates) {
rsi_dbg(ERR_ZONE, "%s: Failed in allocation of mem\n",
__func__);
+ dev_kfree_skb(skb);
return -ENOMEM;
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index ddeb5a709aa3..a87ee9b6585a 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -621,20 +621,18 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
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) {
/*
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
index 06ef47cd6203..5b4c225396f2 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
@@ -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;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
index 68b5c7e92cfb..07cb06da6729 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
@@ -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) {
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
index 36b48be8329c..2b3c78baa9f8 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
@@ -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;
}
diff --git a/drivers/net/wireless/ti/wl18xx/event.h b/drivers/net/wireless/ti/wl18xx/event.h
index 398f3d2c0a6c..a76e98eb8372 100644
--- a/drivers/net/wireless/ti/wl18xx/event.h
+++ b/drivers/net/wireless/ti/wl18xx/event.h
@@ -68,6 +68,26 @@ struct wl18xx_event_mailbox {
/* bitmap of inactive stations (by HLID) */
__le32 inactive_sta_bitmap;
+
+ /* rx BA win size indicated by RX_BA_WIN_SIZE_CHANGE_EVENT_ID */
+ u8 rx_ba_role_id;
+ u8 rx_ba_link_id;
+ u8 rx_ba_win_size;
+ u8 padding;
+
+ /* smart config */
+ u8 sc_ssid_len;
+ u8 sc_pwd_len;
+ u8 sc_token_len;
+ u8 padding1;
+ u8 sc_ssid[32];
+ u8 sc_pwd[32];
+ u8 sc_token[32];
+
+ /* smart config sync channel */
+ u8 sc_sync_channel;
+ u8 sc_sync_band;
+ u8 padding2[2];
} __packed;
int wl18xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event,
diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c
index 1f9a36031b06..16d10281798d 100644
--- a/drivers/net/wireless/ti/wlcore/event.c
+++ b/drivers/net/wireless/ti/wlcore/event.c
@@ -158,6 +158,11 @@ EXPORT_SYMBOL_GPL(wlcore_event_channel_switch);
void wlcore_event_dummy_packet(struct wl1271 *wl)
{
+ if (wl->plt) {
+ wl1271_info("Got DUMMY_PACKET event in PLT mode. FW bug, ignoring.");
+ return;
+ }
+
wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID");
wl1271_tx_dummy_packet(wl);
}
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h
index 630a3fcf65bc..0d4a285cbd7e 100644
--- a/drivers/net/xen-netback/common.h
+++ b/drivers/net/xen-netback/common.h
@@ -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);
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
index ef05c5c49d41..20e9defa1060 100644
--- a/drivers/net/xen-netback/interface.c
+++ b/drivers/net/xen-netback/interface.c
@@ -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)
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index 76665405c5aa..7367208ee8cd 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -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 =
@@ -323,6 +323,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.
*
* This function is responsible for allocating grant operations, meta
@@ -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,
diff --git a/drivers/of/base.c b/drivers/of/base.c
index f72d19b7e5d2..32e969d95319 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -1828,17 +1828,17 @@ int of_update_property(struct device_node *np, struct property *newprop)
next = &(*next)->next;
}
raw_spin_unlock_irqrestore(&devtree_lock, flags);
- if (rc)
- return rc;
+ 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 */
- if (oldprop)
- sysfs_remove_bin_file(&np->kobj, &oldprop->attr);
+ sysfs_remove_bin_file(&np->kobj, &oldprop->attr);
__of_add_property_sysfs(np, newprop);
- if (!found)
- return -ENODEV;
-
return 0;
}
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index fa16a912a927..7a2ef7bb8022 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -491,7 +491,7 @@ static int __init __reserved_mem_reserve_reg(unsigned long node,
* in /reserved-memory matches the values supported by the current implementation,
* also check if ranges property has been provided
*/
-static int __reserved_mem_check_root(unsigned long node)
+static int __init __reserved_mem_check_root(unsigned long node)
{
__be32 *prop;
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 9bcf2cf19357..5aeb89411350 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -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,
@@ -380,6 +380,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
*/
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 404d1daebefa..bd47fbc53dc9 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -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);
diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c
index ae4450070503..fe70b86bcffb 100644
--- a/drivers/of/selftest.c
+++ b/drivers/of/selftest.c
@@ -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;
diff --git a/drivers/of/testcase-data/tests-interrupts.dtsi b/drivers/of/testcase-data/tests-interrupts.dtsi
index c843720bd3e5..da4695f60351 100644
--- a/drivers/of/testcase-data/tests-interrupts.dtsi
+++ b/drivers/of/testcase-data/tests-interrupts.dtsi
@@ -54,5 +54,18 @@
<&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 */
+ };
};
+
};
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
index d3d1cfd51e09..e384e2534594 100644
--- a/drivers/pci/host/pci-mvebu.c
+++ b/drivers/pci/host/pci-mvebu.c
@@ -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;
}
diff --git a/drivers/pci/host/pci-rcar-gen2.c b/drivers/pci/host/pci-rcar-gen2.c
index fd3e3ab56509..4fe349dcaf59 100644
--- a/drivers/pci/host/pci-rcar-gen2.c
+++ b/drivers/pci/host/pci-rcar-gen2.c
@@ -15,6 +15,7 @@
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/of_pci.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
@@ -180,8 +181,13 @@ static int rcar_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
struct pci_sys_data *sys = dev->bus->sysdata;
struct rcar_pci_priv *priv = sys->private_data;
+ int irq;
+
+ irq = of_irq_parse_and_map_pci(dev, slot, pin);
+ if (!irq)
+ irq = priv->irq;
- return priv->irq;
+ return irq;
}
#ifdef CONFIG_PCI_DEBUG
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c
index 330f7e3a32dd..083cf37ca047 100644
--- a/drivers/pci/host/pci-tegra.c
+++ b/drivers/pci/host/pci-tegra.c
@@ -639,10 +639,15 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
static int tegra_pcie_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
{
struct tegra_pcie *pcie = sys_to_pcie(pdev->bus->sysdata);
+ int irq;
tegra_cpuidle_pcie_irqs_in_use();
- return pcie->irq;
+ irq = of_irq_parse_and_map_pci(pdev, slot, pin);
+ if (!irq)
+ irq = pcie->irq;
+
+ return irq;
}
static void tegra_pcie_add_bus(struct pci_bus *bus)
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index 509a29d84509..c4e373294476 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -17,6 +17,7 @@
#include <linux/module.h>
#include <linux/msi.h>
#include <linux/of_address.h>
+#include <linux/of_pci.h>
#include <linux/pci.h>
#include <linux/pci_regs.h>
#include <linux/types.h>
@@ -490,7 +491,7 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
dw_pci.nr_controllers = 1;
dw_pci.private_data = (void **)&pp;
- pci_common_init(&dw_pci);
+ pci_common_init_dev(pp->dev, &dw_pci);
pci_assign_unassigned_resources();
#ifdef CONFIG_PCI_DOMAINS
dw_pci.domain++;
@@ -520,13 +521,13 @@ static void dw_pcie_prog_viewport_cfg1(struct pcie_port *pp, u32 busdev)
dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1,
PCIE_ATU_VIEWPORT);
dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_CFG1, PCIE_ATU_CR1);
- dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
dw_pcie_writel_rc(pp, pp->cfg1_base, PCIE_ATU_LOWER_BASE);
dw_pcie_writel_rc(pp, (pp->cfg1_base >> 32), PCIE_ATU_UPPER_BASE);
dw_pcie_writel_rc(pp, pp->cfg1_base + pp->config.cfg1_size - 1,
PCIE_ATU_LIMIT);
dw_pcie_writel_rc(pp, busdev, PCIE_ATU_LOWER_TARGET);
dw_pcie_writel_rc(pp, 0, PCIE_ATU_UPPER_TARGET);
+ dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
}
static void dw_pcie_prog_viewport_mem_outbound(struct pcie_port *pp)
@@ -535,7 +536,6 @@ static void dw_pcie_prog_viewport_mem_outbound(struct pcie_port *pp)
dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0,
PCIE_ATU_VIEWPORT);
dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_MEM, PCIE_ATU_CR1);
- dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
dw_pcie_writel_rc(pp, pp->mem_base, PCIE_ATU_LOWER_BASE);
dw_pcie_writel_rc(pp, (pp->mem_base >> 32), PCIE_ATU_UPPER_BASE);
dw_pcie_writel_rc(pp, pp->mem_base + pp->config.mem_size - 1,
@@ -543,6 +543,7 @@ static void dw_pcie_prog_viewport_mem_outbound(struct pcie_port *pp)
dw_pcie_writel_rc(pp, pp->config.mem_bus_addr, PCIE_ATU_LOWER_TARGET);
dw_pcie_writel_rc(pp, upper_32_bits(pp->config.mem_bus_addr),
PCIE_ATU_UPPER_TARGET);
+ dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
}
static void dw_pcie_prog_viewport_io_outbound(struct pcie_port *pp)
@@ -551,7 +552,6 @@ static void dw_pcie_prog_viewport_io_outbound(struct pcie_port *pp)
dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1,
PCIE_ATU_VIEWPORT);
dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_IO, PCIE_ATU_CR1);
- dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
dw_pcie_writel_rc(pp, pp->io_base, PCIE_ATU_LOWER_BASE);
dw_pcie_writel_rc(pp, (pp->io_base >> 32), PCIE_ATU_UPPER_BASE);
dw_pcie_writel_rc(pp, pp->io_base + pp->config.io_size - 1,
@@ -559,6 +559,7 @@ static void dw_pcie_prog_viewport_io_outbound(struct pcie_port *pp)
dw_pcie_writel_rc(pp, pp->config.io_bus_addr, PCIE_ATU_LOWER_TARGET);
dw_pcie_writel_rc(pp, upper_32_bits(pp->config.io_bus_addr),
PCIE_ATU_UPPER_TARGET);
+ dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
}
static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
@@ -723,7 +724,7 @@ static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
if (pp) {
pp->root_bus_nr = sys->busnr;
- bus = pci_scan_root_bus(NULL, sys->busnr, &dw_pcie_ops,
+ bus = pci_scan_root_bus(pp->dev, sys->busnr, &dw_pcie_ops,
sys, &sys->resources);
} else {
bus = NULL;
@@ -736,8 +737,13 @@ static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
+ int irq;
+
+ irq = of_irq_parse_and_map_pci(dev, slot, pin);
+ if (!irq)
+ irq = pp->irq;
- return pp->irq;
+ return irq;
}
static void dw_pcie_add_bus(struct pci_bus *bus)
@@ -764,7 +770,7 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
u32 membase;
u32 memlimit;
- /* set the number of lines as 4 */
+ /* set the number of lanes */
dw_pcie_readl_rc(pp, PCIE_PORT_LINK_CONTROL, &val);
val &= ~PORT_LINK_MODE_MASK;
switch (pp->lanes) {
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
index 58499277903a..6efc2ec5e4db 100644
--- a/drivers/pci/hotplug/shpchp_ctrl.c
+++ b/drivers/pci/hotplug/shpchp_ctrl.c
@@ -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))
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 7325d43bf030..759475ef6ff3 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -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; "
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 3bb05f17b9b4..4906c27fa3bd 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -33,6 +33,7 @@ config PHY_MVEBU_SATA
config OMAP_CONTROL_PHY
tristate "OMAP CONTROL PHY Driver"
+ depends on ARCH_OMAP2PLUS || COMPILE_TEST
help
Enable this to add support for the PHY part present in the control
module. This driver has API to power on the USB2 PHY and to write to
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 2faf78edc864..7728518572a4 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -13,8 +13,9 @@ obj-$(CONFIG_TI_PIPE3) += phy-ti-pipe3.o
obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o
obj-$(CONFIG_PHY_EXYNOS5250_SATA) += phy-exynos5250-sata.o
obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o
-obj-$(CONFIG_PHY_SAMSUNG_USB2) += phy-samsung-usb2.o
-obj-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o
-obj-$(CONFIG_PHY_EXYNOS4X12_USB2) += phy-exynos4x12-usb2.o
-obj-$(CONFIG_PHY_EXYNOS5250_USB2) += phy-exynos5250-usb2.o
+obj-$(CONFIG_PHY_SAMSUNG_USB2) += phy-exynos-usb2.o
+phy-exynos-usb2-y += phy-samsung-usb2.o
+phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o
+phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4X12_USB2) += phy-exynos4x12-usb2.o
+phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2) += phy-exynos5250-usb2.o
obj-$(CONFIG_PHY_XGENE) += phy-xgene.o
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index 623b71c54b3e..c64a2f3b2d62 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -64,6 +64,9 @@ static struct phy *phy_lookup(struct device *device, const char *port)
class_dev_iter_init(&iter, phy_class, NULL, NULL);
while ((dev = class_dev_iter_next(&iter))) {
phy = to_phy(dev);
+
+ if (!phy->init_data)
+ continue;
count = phy->init_data->num_consumers;
consumers = phy->init_data->consumers;
while (count--) {
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index e49324032611..e00c02d0a094 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -104,16 +104,16 @@ config PINCTRL_BCM2835
select PINMUX
select PINCONF
-config PINCTRL_CAPRI
- bool "Broadcom Capri pinctrl driver"
+config PINCTRL_BCM281XX
+ bool "Broadcom BCM281xx pinctrl driver"
depends on OF
select PINMUX
select PINCONF
select GENERIC_PINCONF
select REGMAP_MMIO
help
- Say Y here to support Broadcom Capri pinctrl driver, which is used for
- the BCM281xx SoC family, including BCM11130, BCM11140, BCM11351,
+ Say Y here to support Broadcom BCM281xx pinctrl driver, which is used
+ for the BCM281xx SoC family, including BCM11130, BCM11140, BCM11351,
BCM28145, and BCM28155 SoCs. This driver requires the pinctrl
framework. GPIO is provided by a separate GPIO driver.
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 4b835880cf80..6d3fd62b9ae8 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -21,7 +21,7 @@ obj-$(CONFIG_PINCTRL_BF60x) += pinctrl-adi2-bf60x.o
obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o
obj-$(CONFIG_PINCTRL_BCM2835) += pinctrl-bcm2835.o
obj-$(CONFIG_PINCTRL_BAYTRAIL) += pinctrl-baytrail.o
-obj-$(CONFIG_PINCTRL_CAPRI) += pinctrl-capri.o
+obj-$(CONFIG_PINCTRL_BCM281XX) += pinctrl-bcm281xx.o
obj-$(CONFIG_PINCTRL_IMX) += pinctrl-imx.o
obj-$(CONFIG_PINCTRL_IMX1_CORE) += pinctrl-imx1-core.o
obj-$(CONFIG_PINCTRL_IMX27) += pinctrl-imx27.o
diff --git a/drivers/pinctrl/pinctrl-as3722.c b/drivers/pinctrl/pinctrl-as3722.c
index 92ed4b2e3c07..c862f9c0e9ce 100644
--- a/drivers/pinctrl/pinctrl-as3722.c
+++ b/drivers/pinctrl/pinctrl-as3722.c
@@ -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
diff --git a/drivers/pinctrl/pinctrl-bcm281xx.c b/drivers/pinctrl/pinctrl-bcm281xx.c
new file mode 100644
index 000000000000..3bed792b2c03
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-bcm281xx.c
@@ -0,0 +1,1461 @@
+/*
+ * Copyright (C) 2013 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include "core.h"
+#include "pinctrl-utils.h"
+
+/* BCM281XX Pin Control Registers Definitions */
+
+/* Function Select bits are the same for all pin control registers */
+#define BCM281XX_PIN_REG_F_SEL_MASK 0x0700
+#define BCM281XX_PIN_REG_F_SEL_SHIFT 8
+
+/* Standard pin register */
+#define BCM281XX_STD_PIN_REG_DRV_STR_MASK 0x0007
+#define BCM281XX_STD_PIN_REG_DRV_STR_SHIFT 0
+#define BCM281XX_STD_PIN_REG_INPUT_DIS_MASK 0x0008
+#define BCM281XX_STD_PIN_REG_INPUT_DIS_SHIFT 3
+#define BCM281XX_STD_PIN_REG_SLEW_MASK 0x0010
+#define BCM281XX_STD_PIN_REG_SLEW_SHIFT 4
+#define BCM281XX_STD_PIN_REG_PULL_UP_MASK 0x0020
+#define BCM281XX_STD_PIN_REG_PULL_UP_SHIFT 5
+#define BCM281XX_STD_PIN_REG_PULL_DN_MASK 0x0040
+#define BCM281XX_STD_PIN_REG_PULL_DN_SHIFT 6
+#define BCM281XX_STD_PIN_REG_HYST_MASK 0x0080
+#define BCM281XX_STD_PIN_REG_HYST_SHIFT 7
+
+/* I2C pin register */
+#define BCM281XX_I2C_PIN_REG_INPUT_DIS_MASK 0x0004
+#define BCM281XX_I2C_PIN_REG_INPUT_DIS_SHIFT 2
+#define BCM281XX_I2C_PIN_REG_SLEW_MASK 0x0008
+#define BCM281XX_I2C_PIN_REG_SLEW_SHIFT 3
+#define BCM281XX_I2C_PIN_REG_PULL_UP_STR_MASK 0x0070
+#define BCM281XX_I2C_PIN_REG_PULL_UP_STR_SHIFT 4
+
+/* HDMI pin register */
+#define BCM281XX_HDMI_PIN_REG_INPUT_DIS_MASK 0x0008
+#define BCM281XX_HDMI_PIN_REG_INPUT_DIS_SHIFT 3
+#define BCM281XX_HDMI_PIN_REG_MODE_MASK 0x0010
+#define BCM281XX_HDMI_PIN_REG_MODE_SHIFT 4
+
+/**
+ * bcm281xx_pin_type - types of pin register
+ */
+enum bcm281xx_pin_type {
+ BCM281XX_PIN_TYPE_UNKNOWN = 0,
+ BCM281XX_PIN_TYPE_STD,
+ BCM281XX_PIN_TYPE_I2C,
+ BCM281XX_PIN_TYPE_HDMI,
+};
+
+static enum bcm281xx_pin_type std_pin = BCM281XX_PIN_TYPE_STD;
+static enum bcm281xx_pin_type i2c_pin = BCM281XX_PIN_TYPE_I2C;
+static enum bcm281xx_pin_type hdmi_pin = BCM281XX_PIN_TYPE_HDMI;
+
+/**
+ * bcm281xx_pin_function- define pin function
+ */
+struct bcm281xx_pin_function {
+ const char *name;
+ const char * const *groups;
+ const unsigned ngroups;
+};
+
+/**
+ * bcm281xx_pinctrl_data - Broadcom-specific pinctrl data
+ * @reg_base - base of pinctrl registers
+ */
+struct bcm281xx_pinctrl_data {
+ void __iomem *reg_base;
+
+ /* List of all pins */
+ const struct pinctrl_pin_desc *pins;
+ const unsigned npins;
+
+ const struct bcm281xx_pin_function *functions;
+ const unsigned nfunctions;
+
+ struct regmap *regmap;
+};
+
+/*
+ * Pin number definition. The order here must be the same as defined in the
+ * PADCTRLREG block in the RDB.
+ */
+#define BCM281XX_PIN_ADCSYNC 0
+#define BCM281XX_PIN_BAT_RM 1
+#define BCM281XX_PIN_BSC1_SCL 2
+#define BCM281XX_PIN_BSC1_SDA 3
+#define BCM281XX_PIN_BSC2_SCL 4
+#define BCM281XX_PIN_BSC2_SDA 5
+#define BCM281XX_PIN_CLASSGPWR 6
+#define BCM281XX_PIN_CLK_CX8 7
+#define BCM281XX_PIN_CLKOUT_0 8
+#define BCM281XX_PIN_CLKOUT_1 9
+#define BCM281XX_PIN_CLKOUT_2 10
+#define BCM281XX_PIN_CLKOUT_3 11
+#define BCM281XX_PIN_CLKREQ_IN_0 12
+#define BCM281XX_PIN_CLKREQ_IN_1 13
+#define BCM281XX_PIN_CWS_SYS_REQ1 14
+#define BCM281XX_PIN_CWS_SYS_REQ2 15
+#define BCM281XX_PIN_CWS_SYS_REQ3 16
+#define BCM281XX_PIN_DIGMIC1_CLK 17
+#define BCM281XX_PIN_DIGMIC1_DQ 18
+#define BCM281XX_PIN_DIGMIC2_CLK 19
+#define BCM281XX_PIN_DIGMIC2_DQ 20
+#define BCM281XX_PIN_GPEN13 21
+#define BCM281XX_PIN_GPEN14 22
+#define BCM281XX_PIN_GPEN15 23
+#define BCM281XX_PIN_GPIO00 24
+#define BCM281XX_PIN_GPIO01 25
+#define BCM281XX_PIN_GPIO02 26
+#define BCM281XX_PIN_GPIO03 27
+#define BCM281XX_PIN_GPIO04 28
+#define BCM281XX_PIN_GPIO05 29
+#define BCM281XX_PIN_GPIO06 30
+#define BCM281XX_PIN_GPIO07 31
+#define BCM281XX_PIN_GPIO08 32
+#define BCM281XX_PIN_GPIO09 33
+#define BCM281XX_PIN_GPIO10 34
+#define BCM281XX_PIN_GPIO11 35
+#define BCM281XX_PIN_GPIO12 36
+#define BCM281XX_PIN_GPIO13 37
+#define BCM281XX_PIN_GPIO14 38
+#define BCM281XX_PIN_GPS_PABLANK 39
+#define BCM281XX_PIN_GPS_TMARK 40
+#define BCM281XX_PIN_HDMI_SCL 41
+#define BCM281XX_PIN_HDMI_SDA 42
+#define BCM281XX_PIN_IC_DM 43
+#define BCM281XX_PIN_IC_DP 44
+#define BCM281XX_PIN_KP_COL_IP_0 45
+#define BCM281XX_PIN_KP_COL_IP_1 46
+#define BCM281XX_PIN_KP_COL_IP_2 47
+#define BCM281XX_PIN_KP_COL_IP_3 48
+#define BCM281XX_PIN_KP_ROW_OP_0 49
+#define BCM281XX_PIN_KP_ROW_OP_1 50
+#define BCM281XX_PIN_KP_ROW_OP_2 51
+#define BCM281XX_PIN_KP_ROW_OP_3 52
+#define BCM281XX_PIN_LCD_B_0 53
+#define BCM281XX_PIN_LCD_B_1 54
+#define BCM281XX_PIN_LCD_B_2 55
+#define BCM281XX_PIN_LCD_B_3 56
+#define BCM281XX_PIN_LCD_B_4 57
+#define BCM281XX_PIN_LCD_B_5 58
+#define BCM281XX_PIN_LCD_B_6 59
+#define BCM281XX_PIN_LCD_B_7 60
+#define BCM281XX_PIN_LCD_G_0 61
+#define BCM281XX_PIN_LCD_G_1 62
+#define BCM281XX_PIN_LCD_G_2 63
+#define BCM281XX_PIN_LCD_G_3 64
+#define BCM281XX_PIN_LCD_G_4 65
+#define BCM281XX_PIN_LCD_G_5 66
+#define BCM281XX_PIN_LCD_G_6 67
+#define BCM281XX_PIN_LCD_G_7 68
+#define BCM281XX_PIN_LCD_HSYNC 69
+#define BCM281XX_PIN_LCD_OE 70
+#define BCM281XX_PIN_LCD_PCLK 71
+#define BCM281XX_PIN_LCD_R_0 72
+#define BCM281XX_PIN_LCD_R_1 73
+#define BCM281XX_PIN_LCD_R_2 74
+#define BCM281XX_PIN_LCD_R_3 75
+#define BCM281XX_PIN_LCD_R_4 76
+#define BCM281XX_PIN_LCD_R_5 77
+#define BCM281XX_PIN_LCD_R_6 78
+#define BCM281XX_PIN_LCD_R_7 79
+#define BCM281XX_PIN_LCD_VSYNC 80
+#define BCM281XX_PIN_MDMGPIO0 81
+#define BCM281XX_PIN_MDMGPIO1 82
+#define BCM281XX_PIN_MDMGPIO2 83
+#define BCM281XX_PIN_MDMGPIO3 84
+#define BCM281XX_PIN_MDMGPIO4 85
+#define BCM281XX_PIN_MDMGPIO5 86
+#define BCM281XX_PIN_MDMGPIO6 87
+#define BCM281XX_PIN_MDMGPIO7 88
+#define BCM281XX_PIN_MDMGPIO8 89
+#define BCM281XX_PIN_MPHI_DATA_0 90
+#define BCM281XX_PIN_MPHI_DATA_1 91
+#define BCM281XX_PIN_MPHI_DATA_2 92
+#define BCM281XX_PIN_MPHI_DATA_3 93
+#define BCM281XX_PIN_MPHI_DATA_4 94
+#define BCM281XX_PIN_MPHI_DATA_5 95
+#define BCM281XX_PIN_MPHI_DATA_6 96
+#define BCM281XX_PIN_MPHI_DATA_7 97
+#define BCM281XX_PIN_MPHI_DATA_8 98
+#define BCM281XX_PIN_MPHI_DATA_9 99
+#define BCM281XX_PIN_MPHI_DATA_10 100
+#define BCM281XX_PIN_MPHI_DATA_11 101
+#define BCM281XX_PIN_MPHI_DATA_12 102
+#define BCM281XX_PIN_MPHI_DATA_13 103
+#define BCM281XX_PIN_MPHI_DATA_14 104
+#define BCM281XX_PIN_MPHI_DATA_15 105
+#define BCM281XX_PIN_MPHI_HA0 106
+#define BCM281XX_PIN_MPHI_HAT0 107
+#define BCM281XX_PIN_MPHI_HAT1 108
+#define BCM281XX_PIN_MPHI_HCE0_N 109
+#define BCM281XX_PIN_MPHI_HCE1_N 110
+#define BCM281XX_PIN_MPHI_HRD_N 111
+#define BCM281XX_PIN_MPHI_HWR_N 112
+#define BCM281XX_PIN_MPHI_RUN0 113
+#define BCM281XX_PIN_MPHI_RUN1 114
+#define BCM281XX_PIN_MTX_SCAN_CLK 115
+#define BCM281XX_PIN_MTX_SCAN_DATA 116
+#define BCM281XX_PIN_NAND_AD_0 117
+#define BCM281XX_PIN_NAND_AD_1 118
+#define BCM281XX_PIN_NAND_AD_2 119
+#define BCM281XX_PIN_NAND_AD_3 120
+#define BCM281XX_PIN_NAND_AD_4 121
+#define BCM281XX_PIN_NAND_AD_5 122
+#define BCM281XX_PIN_NAND_AD_6 123
+#define BCM281XX_PIN_NAND_AD_7 124
+#define BCM281XX_PIN_NAND_ALE 125
+#define BCM281XX_PIN_NAND_CEN_0 126
+#define BCM281XX_PIN_NAND_CEN_1 127
+#define BCM281XX_PIN_NAND_CLE 128
+#define BCM281XX_PIN_NAND_OEN 129
+#define BCM281XX_PIN_NAND_RDY_0 130
+#define BCM281XX_PIN_NAND_RDY_1 131
+#define BCM281XX_PIN_NAND_WEN 132
+#define BCM281XX_PIN_NAND_WP 133
+#define BCM281XX_PIN_PC1 134
+#define BCM281XX_PIN_PC2 135
+#define BCM281XX_PIN_PMU_INT 136
+#define BCM281XX_PIN_PMU_SCL 137
+#define BCM281XX_PIN_PMU_SDA 138
+#define BCM281XX_PIN_RFST2G_MTSLOTEN3G 139
+#define BCM281XX_PIN_RGMII_0_RX_CTL 140
+#define BCM281XX_PIN_RGMII_0_RXC 141
+#define BCM281XX_PIN_RGMII_0_RXD_0 142
+#define BCM281XX_PIN_RGMII_0_RXD_1 143
+#define BCM281XX_PIN_RGMII_0_RXD_2 144
+#define BCM281XX_PIN_RGMII_0_RXD_3 145
+#define BCM281XX_PIN_RGMII_0_TX_CTL 146
+#define BCM281XX_PIN_RGMII_0_TXC 147
+#define BCM281XX_PIN_RGMII_0_TXD_0 148
+#define BCM281XX_PIN_RGMII_0_TXD_1 149
+#define BCM281XX_PIN_RGMII_0_TXD_2 150
+#define BCM281XX_PIN_RGMII_0_TXD_3 151
+#define BCM281XX_PIN_RGMII_1_RX_CTL 152
+#define BCM281XX_PIN_RGMII_1_RXC 153
+#define BCM281XX_PIN_RGMII_1_RXD_0 154
+#define BCM281XX_PIN_RGMII_1_RXD_1 155
+#define BCM281XX_PIN_RGMII_1_RXD_2 156
+#define BCM281XX_PIN_RGMII_1_RXD_3 157
+#define BCM281XX_PIN_RGMII_1_TX_CTL 158
+#define BCM281XX_PIN_RGMII_1_TXC 159
+#define BCM281XX_PIN_RGMII_1_TXD_0 160
+#define BCM281XX_PIN_RGMII_1_TXD_1 161
+#define BCM281XX_PIN_RGMII_1_TXD_2 162
+#define BCM281XX_PIN_RGMII_1_TXD_3 163
+#define BCM281XX_PIN_RGMII_GPIO_0 164
+#define BCM281XX_PIN_RGMII_GPIO_1 165
+#define BCM281XX_PIN_RGMII_GPIO_2 166
+#define BCM281XX_PIN_RGMII_GPIO_3 167
+#define BCM281XX_PIN_RTXDATA2G_TXDATA3G1 168
+#define BCM281XX_PIN_RTXEN2G_TXDATA3G2 169
+#define BCM281XX_PIN_RXDATA3G0 170
+#define BCM281XX_PIN_RXDATA3G1 171
+#define BCM281XX_PIN_RXDATA3G2 172
+#define BCM281XX_PIN_SDIO1_CLK 173
+#define BCM281XX_PIN_SDIO1_CMD 174
+#define BCM281XX_PIN_SDIO1_DATA_0 175
+#define BCM281XX_PIN_SDIO1_DATA_1 176
+#define BCM281XX_PIN_SDIO1_DATA_2 177
+#define BCM281XX_PIN_SDIO1_DATA_3 178
+#define BCM281XX_PIN_SDIO4_CLK 179
+#define BCM281XX_PIN_SDIO4_CMD 180
+#define BCM281XX_PIN_SDIO4_DATA_0 181
+#define BCM281XX_PIN_SDIO4_DATA_1 182
+#define BCM281XX_PIN_SDIO4_DATA_2 183
+#define BCM281XX_PIN_SDIO4_DATA_3 184
+#define BCM281XX_PIN_SIM_CLK 185
+#define BCM281XX_PIN_SIM_DATA 186
+#define BCM281XX_PIN_SIM_DET 187
+#define BCM281XX_PIN_SIM_RESETN 188
+#define BCM281XX_PIN_SIM2_CLK 189
+#define BCM281XX_PIN_SIM2_DATA 190
+#define BCM281XX_PIN_SIM2_DET 191
+#define BCM281XX_PIN_SIM2_RESETN 192
+#define BCM281XX_PIN_SRI_C 193
+#define BCM281XX_PIN_SRI_D 194
+#define BCM281XX_PIN_SRI_E 195
+#define BCM281XX_PIN_SSP_EXTCLK 196
+#define BCM281XX_PIN_SSP0_CLK 197
+#define BCM281XX_PIN_SSP0_FS 198
+#define BCM281XX_PIN_SSP0_RXD 199
+#define BCM281XX_PIN_SSP0_TXD 200
+#define BCM281XX_PIN_SSP2_CLK 201
+#define BCM281XX_PIN_SSP2_FS_0 202
+#define BCM281XX_PIN_SSP2_FS_1 203
+#define BCM281XX_PIN_SSP2_FS_2 204
+#define BCM281XX_PIN_SSP2_FS_3 205
+#define BCM281XX_PIN_SSP2_RXD_0 206
+#define BCM281XX_PIN_SSP2_RXD_1 207
+#define BCM281XX_PIN_SSP2_TXD_0 208
+#define BCM281XX_PIN_SSP2_TXD_1 209
+#define BCM281XX_PIN_SSP3_CLK 210
+#define BCM281XX_PIN_SSP3_FS 211
+#define BCM281XX_PIN_SSP3_RXD 212
+#define BCM281XX_PIN_SSP3_TXD 213
+#define BCM281XX_PIN_SSP4_CLK 214
+#define BCM281XX_PIN_SSP4_FS 215
+#define BCM281XX_PIN_SSP4_RXD 216
+#define BCM281XX_PIN_SSP4_TXD 217
+#define BCM281XX_PIN_SSP5_CLK 218
+#define BCM281XX_PIN_SSP5_FS 219
+#define BCM281XX_PIN_SSP5_RXD 220
+#define BCM281XX_PIN_SSP5_TXD 221
+#define BCM281XX_PIN_SSP6_CLK 222
+#define BCM281XX_PIN_SSP6_FS 223
+#define BCM281XX_PIN_SSP6_RXD 224
+#define BCM281XX_PIN_SSP6_TXD 225
+#define BCM281XX_PIN_STAT_1 226
+#define BCM281XX_PIN_STAT_2 227
+#define BCM281XX_PIN_SYSCLKEN 228
+#define BCM281XX_PIN_TRACECLK 229
+#define BCM281XX_PIN_TRACEDT00 230
+#define BCM281XX_PIN_TRACEDT01 231
+#define BCM281XX_PIN_TRACEDT02 232
+#define BCM281XX_PIN_TRACEDT03 233
+#define BCM281XX_PIN_TRACEDT04 234
+#define BCM281XX_PIN_TRACEDT05 235
+#define BCM281XX_PIN_TRACEDT06 236
+#define BCM281XX_PIN_TRACEDT07 237
+#define BCM281XX_PIN_TRACEDT08 238
+#define BCM281XX_PIN_TRACEDT09 239
+#define BCM281XX_PIN_TRACEDT10 240
+#define BCM281XX_PIN_TRACEDT11 241
+#define BCM281XX_PIN_TRACEDT12 242
+#define BCM281XX_PIN_TRACEDT13 243
+#define BCM281XX_PIN_TRACEDT14 244
+#define BCM281XX_PIN_TRACEDT15 245
+#define BCM281XX_PIN_TXDATA3G0 246
+#define BCM281XX_PIN_TXPWRIND 247
+#define BCM281XX_PIN_UARTB1_UCTS 248
+#define BCM281XX_PIN_UARTB1_URTS 249
+#define BCM281XX_PIN_UARTB1_URXD 250
+#define BCM281XX_PIN_UARTB1_UTXD 251
+#define BCM281XX_PIN_UARTB2_URXD 252
+#define BCM281XX_PIN_UARTB2_UTXD 253
+#define BCM281XX_PIN_UARTB3_UCTS 254
+#define BCM281XX_PIN_UARTB3_URTS 255
+#define BCM281XX_PIN_UARTB3_URXD 256
+#define BCM281XX_PIN_UARTB3_UTXD 257
+#define BCM281XX_PIN_UARTB4_UCTS 258
+#define BCM281XX_PIN_UARTB4_URTS 259
+#define BCM281XX_PIN_UARTB4_URXD 260
+#define BCM281XX_PIN_UARTB4_UTXD 261
+#define BCM281XX_PIN_VC_CAM1_SCL 262
+#define BCM281XX_PIN_VC_CAM1_SDA 263
+#define BCM281XX_PIN_VC_CAM2_SCL 264
+#define BCM281XX_PIN_VC_CAM2_SDA 265
+#define BCM281XX_PIN_VC_CAM3_SCL 266
+#define BCM281XX_PIN_VC_CAM3_SDA 267
+
+#define BCM281XX_PIN_DESC(a, b, c) \
+ { .number = a, .name = b, .drv_data = &c##_pin }
+
+/*
+ * Pin description definition. The order here must be the same as defined in
+ * the PADCTRLREG block in the RDB, since the pin number is used as an index
+ * into this array.
+ */
+static const struct pinctrl_pin_desc bcm281xx_pinctrl_pins[] = {
+ BCM281XX_PIN_DESC(BCM281XX_PIN_ADCSYNC, "adcsync", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_BAT_RM, "bat_rm", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_BSC1_SCL, "bsc1_scl", i2c),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_BSC1_SDA, "bsc1_sda", i2c),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_BSC2_SCL, "bsc2_scl", i2c),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_BSC2_SDA, "bsc2_sda", i2c),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_CLASSGPWR, "classgpwr", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_CLK_CX8, "clk_cx8", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_CLKOUT_0, "clkout_0", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_CLKOUT_1, "clkout_1", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_CLKOUT_2, "clkout_2", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_CLKOUT_3, "clkout_3", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_CLKREQ_IN_0, "clkreq_in_0", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_CLKREQ_IN_1, "clkreq_in_1", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_CWS_SYS_REQ1, "cws_sys_req1", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_CWS_SYS_REQ2, "cws_sys_req2", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_CWS_SYS_REQ3, "cws_sys_req3", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_DIGMIC1_CLK, "digmic1_clk", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_DIGMIC1_DQ, "digmic1_dq", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_DIGMIC2_CLK, "digmic2_clk", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_DIGMIC2_DQ, "digmic2_dq", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_GPEN13, "gpen13", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_GPEN14, "gpen14", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_GPEN15, "gpen15", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO00, "gpio00", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO01, "gpio01", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO02, "gpio02", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO03, "gpio03", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO04, "gpio04", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO05, "gpio05", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO06, "gpio06", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO07, "gpio07", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO08, "gpio08", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO09, "gpio09", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO10, "gpio10", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO11, "gpio11", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO12, "gpio12", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO13, "gpio13", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_GPIO14, "gpio14", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_GPS_PABLANK, "gps_pablank", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_GPS_TMARK, "gps_tmark", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_HDMI_SCL, "hdmi_scl", hdmi),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_HDMI_SDA, "hdmi_sda", hdmi),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_IC_DM, "ic_dm", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_IC_DP, "ic_dp", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_KP_COL_IP_0, "kp_col_ip_0", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_KP_COL_IP_1, "kp_col_ip_1", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_KP_COL_IP_2, "kp_col_ip_2", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_KP_COL_IP_3, "kp_col_ip_3", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_KP_ROW_OP_0, "kp_row_op_0", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_KP_ROW_OP_1, "kp_row_op_1", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_KP_ROW_OP_2, "kp_row_op_2", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_KP_ROW_OP_3, "kp_row_op_3", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_B_0, "lcd_b_0", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_B_1, "lcd_b_1", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_B_2, "lcd_b_2", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_B_3, "lcd_b_3", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_B_4, "lcd_b_4", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_B_5, "lcd_b_5", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_B_6, "lcd_b_6", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_B_7, "lcd_b_7", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_G_0, "lcd_g_0", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_G_1, "lcd_g_1", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_G_2, "lcd_g_2", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_G_3, "lcd_g_3", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_G_4, "lcd_g_4", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_G_5, "lcd_g_5", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_G_6, "lcd_g_6", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_G_7, "lcd_g_7", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_HSYNC, "lcd_hsync", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_OE, "lcd_oe", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_PCLK, "lcd_pclk", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_R_0, "lcd_r_0", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_R_1, "lcd_r_1", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_R_2, "lcd_r_2", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_R_3, "lcd_r_3", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_R_4, "lcd_r_4", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_R_5, "lcd_r_5", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_R_6, "lcd_r_6", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_R_7, "lcd_r_7", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_LCD_VSYNC, "lcd_vsync", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO0, "mdmgpio0", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO1, "mdmgpio1", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO2, "mdmgpio2", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO3, "mdmgpio3", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO4, "mdmgpio4", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO5, "mdmgpio5", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO6, "mdmgpio6", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO7, "mdmgpio7", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MDMGPIO8, "mdmgpio8", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_0, "mphi_data_0", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_1, "mphi_data_1", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_2, "mphi_data_2", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_3, "mphi_data_3", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_4, "mphi_data_4", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_5, "mphi_data_5", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_6, "mphi_data_6", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_7, "mphi_data_7", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_8, "mphi_data_8", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_9, "mphi_data_9", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_10, "mphi_data_10", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_11, "mphi_data_11", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_12, "mphi_data_12", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_13, "mphi_data_13", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_14, "mphi_data_14", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_DATA_15, "mphi_data_15", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_HA0, "mphi_ha0", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_HAT0, "mphi_hat0", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_HAT1, "mphi_hat1", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_HCE0_N, "mphi_hce0_n", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_HCE1_N, "mphi_hce1_n", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_HRD_N, "mphi_hrd_n", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_HWR_N, "mphi_hwr_n", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_RUN0, "mphi_run0", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MPHI_RUN1, "mphi_run1", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MTX_SCAN_CLK, "mtx_scan_clk", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_MTX_SCAN_DATA, "mtx_scan_data", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_AD_0, "nand_ad_0", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_AD_1, "nand_ad_1", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_AD_2, "nand_ad_2", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_AD_3, "nand_ad_3", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_AD_4, "nand_ad_4", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_AD_5, "nand_ad_5", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_AD_6, "nand_ad_6", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_AD_7, "nand_ad_7", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_ALE, "nand_ale", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_CEN_0, "nand_cen_0", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_CEN_1, "nand_cen_1", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_CLE, "nand_cle", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_OEN, "nand_oen", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_RDY_0, "nand_rdy_0", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_RDY_1, "nand_rdy_1", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_WEN, "nand_wen", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_NAND_WP, "nand_wp", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_PC1, "pc1", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_PC2, "pc2", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_PMU_INT, "pmu_int", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_PMU_SCL, "pmu_scl", i2c),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_PMU_SDA, "pmu_sda", i2c),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RFST2G_MTSLOTEN3G, "rfst2g_mtsloten3g",
+ std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_RX_CTL, "rgmii_0_rx_ctl", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_RXC, "rgmii_0_rxc", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_RXD_0, "rgmii_0_rxd_0", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_RXD_1, "rgmii_0_rxd_1", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_RXD_2, "rgmii_0_rxd_2", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_RXD_3, "rgmii_0_rxd_3", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_TX_CTL, "rgmii_0_tx_ctl", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_TXC, "rgmii_0_txc", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_TXD_0, "rgmii_0_txd_0", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_TXD_1, "rgmii_0_txd_1", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_TXD_2, "rgmii_0_txd_2", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_0_TXD_3, "rgmii_0_txd_3", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_RX_CTL, "rgmii_1_rx_ctl", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_RXC, "rgmii_1_rxc", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_RXD_0, "rgmii_1_rxd_0", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_RXD_1, "rgmii_1_rxd_1", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_RXD_2, "rgmii_1_rxd_2", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_RXD_3, "rgmii_1_rxd_3", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_TX_CTL, "rgmii_1_tx_ctl", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_TXC, "rgmii_1_txc", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_TXD_0, "rgmii_1_txd_0", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_TXD_1, "rgmii_1_txd_1", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_TXD_2, "rgmii_1_txd_2", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_1_TXD_3, "rgmii_1_txd_3", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_GPIO_0, "rgmii_gpio_0", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_GPIO_1, "rgmii_gpio_1", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_GPIO_2, "rgmii_gpio_2", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RGMII_GPIO_3, "rgmii_gpio_3", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RTXDATA2G_TXDATA3G1,
+ "rtxdata2g_txdata3g1", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RTXEN2G_TXDATA3G2, "rtxen2g_txdata3g2",
+ std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RXDATA3G0, "rxdata3g0", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RXDATA3G1, "rxdata3g1", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_RXDATA3G2, "rxdata3g2", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO1_CLK, "sdio1_clk", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO1_CMD, "sdio1_cmd", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO1_DATA_0, "sdio1_data_0", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO1_DATA_1, "sdio1_data_1", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO1_DATA_2, "sdio1_data_2", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO1_DATA_3, "sdio1_data_3", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO4_CLK, "sdio4_clk", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO4_CMD, "sdio4_cmd", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO4_DATA_0, "sdio4_data_0", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO4_DATA_1, "sdio4_data_1", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO4_DATA_2, "sdio4_data_2", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SDIO4_DATA_3, "sdio4_data_3", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SIM_CLK, "sim_clk", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SIM_DATA, "sim_data", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SIM_DET, "sim_det", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SIM_RESETN, "sim_resetn", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SIM2_CLK, "sim2_clk", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SIM2_DATA, "sim2_data", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SIM2_DET, "sim2_det", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SIM2_RESETN, "sim2_resetn", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SRI_C, "sri_c", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SRI_D, "sri_d", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SRI_E, "sri_e", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SSP_EXTCLK, "ssp_extclk", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SSP0_CLK, "ssp0_clk", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SSP0_FS, "ssp0_fs", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SSP0_RXD, "ssp0_rxd", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SSP0_TXD, "ssp0_txd", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_CLK, "ssp2_clk", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_FS_0, "ssp2_fs_0", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_FS_1, "ssp2_fs_1", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_FS_2, "ssp2_fs_2", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_FS_3, "ssp2_fs_3", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_RXD_0, "ssp2_rxd_0", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_RXD_1, "ssp2_rxd_1", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_TXD_0, "ssp2_txd_0", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SSP2_TXD_1, "ssp2_txd_1", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SSP3_CLK, "ssp3_clk", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SSP3_FS, "ssp3_fs", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SSP3_RXD, "ssp3_rxd", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SSP3_TXD, "ssp3_txd", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SSP4_CLK, "ssp4_clk", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SSP4_FS, "ssp4_fs", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SSP4_RXD, "ssp4_rxd", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SSP4_TXD, "ssp4_txd", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SSP5_CLK, "ssp5_clk", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SSP5_FS, "ssp5_fs", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SSP5_RXD, "ssp5_rxd", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SSP5_TXD, "ssp5_txd", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SSP6_CLK, "ssp6_clk", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SSP6_FS, "ssp6_fs", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SSP6_RXD, "ssp6_rxd", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SSP6_TXD, "ssp6_txd", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_STAT_1, "stat_1", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_STAT_2, "stat_2", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_SYSCLKEN, "sysclken", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_TRACECLK, "traceclk", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT00, "tracedt00", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT01, "tracedt01", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT02, "tracedt02", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT03, "tracedt03", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT04, "tracedt04", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT05, "tracedt05", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT06, "tracedt06", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT07, "tracedt07", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT08, "tracedt08", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT09, "tracedt09", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT10, "tracedt10", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT11, "tracedt11", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT12, "tracedt12", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT13, "tracedt13", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT14, "tracedt14", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_TRACEDT15, "tracedt15", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_TXDATA3G0, "txdata3g0", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_TXPWRIND, "txpwrind", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB1_UCTS, "uartb1_ucts", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB1_URTS, "uartb1_urts", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB1_URXD, "uartb1_urxd", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB1_UTXD, "uartb1_utxd", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB2_URXD, "uartb2_urxd", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB2_UTXD, "uartb2_utxd", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB3_UCTS, "uartb3_ucts", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB3_URTS, "uartb3_urts", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB3_URXD, "uartb3_urxd", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB3_UTXD, "uartb3_utxd", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB4_UCTS, "uartb4_ucts", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB4_URTS, "uartb4_urts", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB4_URXD, "uartb4_urxd", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_UARTB4_UTXD, "uartb4_utxd", std),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_VC_CAM1_SCL, "vc_cam1_scl", i2c),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_VC_CAM1_SDA, "vc_cam1_sda", i2c),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_VC_CAM2_SCL, "vc_cam2_scl", i2c),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_VC_CAM2_SDA, "vc_cam2_sda", i2c),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_VC_CAM3_SCL, "vc_cam3_scl", i2c),
+ BCM281XX_PIN_DESC(BCM281XX_PIN_VC_CAM3_SDA, "vc_cam3_sda", i2c),
+};
+
+static const char * const bcm281xx_alt_groups[] = {
+ "adcsync",
+ "bat_rm",
+ "bsc1_scl",
+ "bsc1_sda",
+ "bsc2_scl",
+ "bsc2_sda",
+ "classgpwr",
+ "clk_cx8",
+ "clkout_0",
+ "clkout_1",
+ "clkout_2",
+ "clkout_3",
+ "clkreq_in_0",
+ "clkreq_in_1",
+ "cws_sys_req1",
+ "cws_sys_req2",
+ "cws_sys_req3",
+ "digmic1_clk",
+ "digmic1_dq",
+ "digmic2_clk",
+ "digmic2_dq",
+ "gpen13",
+ "gpen14",
+ "gpen15",
+ "gpio00",
+ "gpio01",
+ "gpio02",
+ "gpio03",
+ "gpio04",
+ "gpio05",
+ "gpio06",
+ "gpio07",
+ "gpio08",
+ "gpio09",
+ "gpio10",
+ "gpio11",
+ "gpio12",
+ "gpio13",
+ "gpio14",
+ "gps_pablank",
+ "gps_tmark",
+ "hdmi_scl",
+ "hdmi_sda",
+ "ic_dm",
+ "ic_dp",
+ "kp_col_ip_0",
+ "kp_col_ip_1",
+ "kp_col_ip_2",
+ "kp_col_ip_3",
+ "kp_row_op_0",
+ "kp_row_op_1",
+ "kp_row_op_2",
+ "kp_row_op_3",
+ "lcd_b_0",
+ "lcd_b_1",
+ "lcd_b_2",
+ "lcd_b_3",
+ "lcd_b_4",
+ "lcd_b_5",
+ "lcd_b_6",
+ "lcd_b_7",
+ "lcd_g_0",
+ "lcd_g_1",
+ "lcd_g_2",
+ "lcd_g_3",
+ "lcd_g_4",
+ "lcd_g_5",
+ "lcd_g_6",
+ "lcd_g_7",
+ "lcd_hsync",
+ "lcd_oe",
+ "lcd_pclk",
+ "lcd_r_0",
+ "lcd_r_1",
+ "lcd_r_2",
+ "lcd_r_3",
+ "lcd_r_4",
+ "lcd_r_5",
+ "lcd_r_6",
+ "lcd_r_7",
+ "lcd_vsync",
+ "mdmgpio0",
+ "mdmgpio1",
+ "mdmgpio2",
+ "mdmgpio3",
+ "mdmgpio4",
+ "mdmgpio5",
+ "mdmgpio6",
+ "mdmgpio7",
+ "mdmgpio8",
+ "mphi_data_0",
+ "mphi_data_1",
+ "mphi_data_2",
+ "mphi_data_3",
+ "mphi_data_4",
+ "mphi_data_5",
+ "mphi_data_6",
+ "mphi_data_7",
+ "mphi_data_8",
+ "mphi_data_9",
+ "mphi_data_10",
+ "mphi_data_11",
+ "mphi_data_12",
+ "mphi_data_13",
+ "mphi_data_14",
+ "mphi_data_15",
+ "mphi_ha0",
+ "mphi_hat0",
+ "mphi_hat1",
+ "mphi_hce0_n",
+ "mphi_hce1_n",
+ "mphi_hrd_n",
+ "mphi_hwr_n",
+ "mphi_run0",
+ "mphi_run1",
+ "mtx_scan_clk",
+ "mtx_scan_data",
+ "nand_ad_0",
+ "nand_ad_1",
+ "nand_ad_2",
+ "nand_ad_3",
+ "nand_ad_4",
+ "nand_ad_5",
+ "nand_ad_6",
+ "nand_ad_7",
+ "nand_ale",
+ "nand_cen_0",
+ "nand_cen_1",
+ "nand_cle",
+ "nand_oen",
+ "nand_rdy_0",
+ "nand_rdy_1",
+ "nand_wen",
+ "nand_wp",
+ "pc1",
+ "pc2",
+ "pmu_int",
+ "pmu_scl",
+ "pmu_sda",
+ "rfst2g_mtsloten3g",
+ "rgmii_0_rx_ctl",
+ "rgmii_0_rxc",
+ "rgmii_0_rxd_0",
+ "rgmii_0_rxd_1",
+ "rgmii_0_rxd_2",
+ "rgmii_0_rxd_3",
+ "rgmii_0_tx_ctl",
+ "rgmii_0_txc",
+ "rgmii_0_txd_0",
+ "rgmii_0_txd_1",
+ "rgmii_0_txd_2",
+ "rgmii_0_txd_3",
+ "rgmii_1_rx_ctl",
+ "rgmii_1_rxc",
+ "rgmii_1_rxd_0",
+ "rgmii_1_rxd_1",
+ "rgmii_1_rxd_2",
+ "rgmii_1_rxd_3",
+ "rgmii_1_tx_ctl",
+ "rgmii_1_txc",
+ "rgmii_1_txd_0",
+ "rgmii_1_txd_1",
+ "rgmii_1_txd_2",
+ "rgmii_1_txd_3",
+ "rgmii_gpio_0",
+ "rgmii_gpio_1",
+ "rgmii_gpio_2",
+ "rgmii_gpio_3",
+ "rtxdata2g_txdata3g1",
+ "rtxen2g_txdata3g2",
+ "rxdata3g0",
+ "rxdata3g1",
+ "rxdata3g2",
+ "sdio1_clk",
+ "sdio1_cmd",
+ "sdio1_data_0",
+ "sdio1_data_1",
+ "sdio1_data_2",
+ "sdio1_data_3",
+ "sdio4_clk",
+ "sdio4_cmd",
+ "sdio4_data_0",
+ "sdio4_data_1",
+ "sdio4_data_2",
+ "sdio4_data_3",
+ "sim_clk",
+ "sim_data",
+ "sim_det",
+ "sim_resetn",
+ "sim2_clk",
+ "sim2_data",
+ "sim2_det",
+ "sim2_resetn",
+ "sri_c",
+ "sri_d",
+ "sri_e",
+ "ssp_extclk",
+ "ssp0_clk",
+ "ssp0_fs",
+ "ssp0_rxd",
+ "ssp0_txd",
+ "ssp2_clk",
+ "ssp2_fs_0",
+ "ssp2_fs_1",
+ "ssp2_fs_2",
+ "ssp2_fs_3",
+ "ssp2_rxd_0",
+ "ssp2_rxd_1",
+ "ssp2_txd_0",
+ "ssp2_txd_1",
+ "ssp3_clk",
+ "ssp3_fs",
+ "ssp3_rxd",
+ "ssp3_txd",
+ "ssp4_clk",
+ "ssp4_fs",
+ "ssp4_rxd",
+ "ssp4_txd",
+ "ssp5_clk",
+ "ssp5_fs",
+ "ssp5_rxd",
+ "ssp5_txd",
+ "ssp6_clk",
+ "ssp6_fs",
+ "ssp6_rxd",
+ "ssp6_txd",
+ "stat_1",
+ "stat_2",
+ "sysclken",
+ "traceclk",
+ "tracedt00",
+ "tracedt01",
+ "tracedt02",
+ "tracedt03",
+ "tracedt04",
+ "tracedt05",
+ "tracedt06",
+ "tracedt07",
+ "tracedt08",
+ "tracedt09",
+ "tracedt10",
+ "tracedt11",
+ "tracedt12",
+ "tracedt13",
+ "tracedt14",
+ "tracedt15",
+ "txdata3g0",
+ "txpwrind",
+ "uartb1_ucts",
+ "uartb1_urts",
+ "uartb1_urxd",
+ "uartb1_utxd",
+ "uartb2_urxd",
+ "uartb2_utxd",
+ "uartb3_ucts",
+ "uartb3_urts",
+ "uartb3_urxd",
+ "uartb3_utxd",
+ "uartb4_ucts",
+ "uartb4_urts",
+ "uartb4_urxd",
+ "uartb4_utxd",
+ "vc_cam1_scl",
+ "vc_cam1_sda",
+ "vc_cam2_scl",
+ "vc_cam2_sda",
+ "vc_cam3_scl",
+ "vc_cam3_sda",
+};
+
+/* Every pin can implement all ALT1-ALT4 functions */
+#define BCM281XX_PIN_FUNCTION(fcn_name) \
+{ \
+ .name = #fcn_name, \
+ .groups = bcm281xx_alt_groups, \
+ .ngroups = ARRAY_SIZE(bcm281xx_alt_groups), \
+}
+
+static const struct bcm281xx_pin_function bcm281xx_functions[] = {
+ BCM281XX_PIN_FUNCTION(alt1),
+ BCM281XX_PIN_FUNCTION(alt2),
+ BCM281XX_PIN_FUNCTION(alt3),
+ BCM281XX_PIN_FUNCTION(alt4),
+};
+
+static struct bcm281xx_pinctrl_data bcm281xx_pinctrl = {
+ .pins = bcm281xx_pinctrl_pins,
+ .npins = ARRAY_SIZE(bcm281xx_pinctrl_pins),
+ .functions = bcm281xx_functions,
+ .nfunctions = ARRAY_SIZE(bcm281xx_functions),
+};
+
+static inline enum bcm281xx_pin_type pin_type_get(struct pinctrl_dev *pctldev,
+ unsigned pin)
+{
+ struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+
+ if (pin >= pdata->npins)
+ return BCM281XX_PIN_TYPE_UNKNOWN;
+
+ return *(enum bcm281xx_pin_type *)(pdata->pins[pin].drv_data);
+}
+
+#define BCM281XX_PIN_SHIFT(type, param) \
+ (BCM281XX_ ## type ## _PIN_REG_ ## param ## _SHIFT)
+
+#define BCM281XX_PIN_MASK(type, param) \
+ (BCM281XX_ ## type ## _PIN_REG_ ## param ## _MASK)
+
+/*
+ * This helper function is used to build up the value and mask used to write to
+ * a pin register, but does not actually write to the register.
+ */
+static inline void bcm281xx_pin_update(u32 *reg_val, u32 *reg_mask,
+ u32 param_val, u32 param_shift,
+ u32 param_mask)
+{
+ *reg_val &= ~param_mask;
+ *reg_val |= (param_val << param_shift) & param_mask;
+ *reg_mask |= param_mask;
+}
+
+static struct regmap_config bcm281xx_pinctrl_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = BCM281XX_PIN_VC_CAM3_SDA,
+};
+
+static int bcm281xx_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+ struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+
+ return pdata->npins;
+}
+
+static const char *bcm281xx_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned group)
+{
+ struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+
+ return pdata->pins[group].name;
+}
+
+static int bcm281xx_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned group,
+ const unsigned **pins,
+ unsigned *num_pins)
+{
+ struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+
+ *pins = &pdata->pins[group].number;
+ *num_pins = 1;
+
+ return 0;
+}
+
+static void bcm281xx_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s,
+ unsigned offset)
+{
+ seq_printf(s, " %s", dev_name(pctldev->dev));
+}
+
+static struct pinctrl_ops bcm281xx_pinctrl_ops = {
+ .get_groups_count = bcm281xx_pinctrl_get_groups_count,
+ .get_group_name = bcm281xx_pinctrl_get_group_name,
+ .get_group_pins = bcm281xx_pinctrl_get_group_pins,
+ .pin_dbg_show = bcm281xx_pinctrl_pin_dbg_show,
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+ .dt_free_map = pinctrl_utils_dt_free_map,
+};
+
+static int bcm281xx_pinctrl_get_fcns_count(struct pinctrl_dev *pctldev)
+{
+ struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+
+ return pdata->nfunctions;
+}
+
+static const char *bcm281xx_pinctrl_get_fcn_name(struct pinctrl_dev *pctldev,
+ unsigned function)
+{
+ struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+
+ return pdata->functions[function].name;
+}
+
+static int bcm281xx_pinctrl_get_fcn_groups(struct pinctrl_dev *pctldev,
+ unsigned function,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+
+ *groups = pdata->functions[function].groups;
+ *num_groups = pdata->functions[function].ngroups;
+
+ return 0;
+}
+
+static int bcm281xx_pinmux_enable(struct pinctrl_dev *pctldev,
+ unsigned function,
+ unsigned group)
+{
+ struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+ const struct bcm281xx_pin_function *f = &pdata->functions[function];
+ u32 offset = 4 * pdata->pins[group].number;
+ int rc = 0;
+
+ dev_dbg(pctldev->dev,
+ "%s(): Enable function %s (%d) of pin %s (%d) @offset 0x%x.\n",
+ __func__, f->name, function, pdata->pins[group].name,
+ pdata->pins[group].number, offset);
+
+ rc = regmap_update_bits(pdata->regmap, offset,
+ BCM281XX_PIN_REG_F_SEL_MASK,
+ function << BCM281XX_PIN_REG_F_SEL_SHIFT);
+ if (rc)
+ dev_err(pctldev->dev,
+ "Error updating register for pin %s (%d).\n",
+ pdata->pins[group].name, pdata->pins[group].number);
+
+ return rc;
+}
+
+static struct pinmux_ops bcm281xx_pinctrl_pinmux_ops = {
+ .get_functions_count = bcm281xx_pinctrl_get_fcns_count,
+ .get_function_name = bcm281xx_pinctrl_get_fcn_name,
+ .get_function_groups = bcm281xx_pinctrl_get_fcn_groups,
+ .enable = bcm281xx_pinmux_enable,
+};
+
+static int bcm281xx_pinctrl_pin_config_get(struct pinctrl_dev *pctldev,
+ unsigned pin,
+ unsigned long *config)
+{
+ return -ENOTSUPP;
+}
+
+
+/* Goes through the configs and update register val/mask */
+static int bcm281xx_std_pin_update(struct pinctrl_dev *pctldev,
+ unsigned pin,
+ unsigned long *configs,
+ unsigned num_configs,
+ u32 *val,
+ u32 *mask)
+{
+ struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+ int i;
+ enum pin_config_param param;
+ u16 arg;
+
+ for (i = 0; i < num_configs; i++) {
+ param = pinconf_to_config_param(configs[i]);
+ arg = pinconf_to_config_argument(configs[i]);
+
+ switch (param) {
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ arg = (arg >= 1 ? 1 : 0);
+ bcm281xx_pin_update(val, mask, arg,
+ BCM281XX_PIN_SHIFT(STD, HYST),
+ BCM281XX_PIN_MASK(STD, HYST));
+ break;
+ /*
+ * The pin bias can only be one of pull-up, pull-down, or
+ * disable. The user does not need to specify a value for the
+ * property, and the default value from pinconf-generic is
+ * ignored.
+ */
+ case PIN_CONFIG_BIAS_DISABLE:
+ bcm281xx_pin_update(val, mask, 0,
+ BCM281XX_PIN_SHIFT(STD, PULL_UP),
+ BCM281XX_PIN_MASK(STD, PULL_UP));
+ bcm281xx_pin_update(val, mask, 0,
+ BCM281XX_PIN_SHIFT(STD, PULL_DN),
+ BCM281XX_PIN_MASK(STD, PULL_DN));
+ break;
+
+ case PIN_CONFIG_BIAS_PULL_UP:
+ bcm281xx_pin_update(val, mask, 1,
+ BCM281XX_PIN_SHIFT(STD, PULL_UP),
+ BCM281XX_PIN_MASK(STD, PULL_UP));
+ bcm281xx_pin_update(val, mask, 0,
+ BCM281XX_PIN_SHIFT(STD, PULL_DN),
+ BCM281XX_PIN_MASK(STD, PULL_DN));
+ break;
+
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ bcm281xx_pin_update(val, mask, 0,
+ BCM281XX_PIN_SHIFT(STD, PULL_UP),
+ BCM281XX_PIN_MASK(STD, PULL_UP));
+ bcm281xx_pin_update(val, mask, 1,
+ BCM281XX_PIN_SHIFT(STD, PULL_DN),
+ BCM281XX_PIN_MASK(STD, PULL_DN));
+ break;
+
+ case PIN_CONFIG_SLEW_RATE:
+ arg = (arg >= 1 ? 1 : 0);
+ bcm281xx_pin_update(val, mask, arg,
+ BCM281XX_PIN_SHIFT(STD, SLEW),
+ BCM281XX_PIN_MASK(STD, SLEW));
+ break;
+
+ case PIN_CONFIG_INPUT_ENABLE:
+ /* inversed since register is for input _disable_ */
+ arg = (arg >= 1 ? 0 : 1);
+ bcm281xx_pin_update(val, mask, arg,
+ BCM281XX_PIN_SHIFT(STD, INPUT_DIS),
+ BCM281XX_PIN_MASK(STD, INPUT_DIS));
+ break;
+
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ /* Valid range is 2-16 mA, even numbers only */
+ if ((arg < 2) || (arg > 16) || (arg % 2)) {
+ dev_err(pctldev->dev,
+ "Invalid Drive Strength value (%d) for "
+ "pin %s (%d). Valid values are "
+ "(2..16) mA, even numbers only.\n",
+ arg, pdata->pins[pin].name, pin);
+ return -EINVAL;
+ }
+ bcm281xx_pin_update(val, mask, (arg/2)-1,
+ BCM281XX_PIN_SHIFT(STD, DRV_STR),
+ BCM281XX_PIN_MASK(STD, DRV_STR));
+ break;
+
+ default:
+ dev_err(pctldev->dev,
+ "Unrecognized pin config %d for pin %s (%d).\n",
+ param, pdata->pins[pin].name, pin);
+ return -EINVAL;
+
+ } /* switch config */
+ } /* for each config */
+
+ return 0;
+}
+
+/*
+ * The pull-up strength for an I2C pin is represented by bits 4-6 in the
+ * register with the following mapping:
+ * 0b000: No pull-up
+ * 0b001: 1200 Ohm
+ * 0b010: 1800 Ohm
+ * 0b011: 720 Ohm
+ * 0b100: 2700 Ohm
+ * 0b101: 831 Ohm
+ * 0b110: 1080 Ohm
+ * 0b111: 568 Ohm
+ * This array maps pull-up strength in Ohms to register values (1+index).
+ */
+static const u16 bcm281xx_pullup_map[] = {
+ 1200, 1800, 720, 2700, 831, 1080, 568
+};
+
+/* Goes through the configs and update register val/mask */
+static int bcm281xx_i2c_pin_update(struct pinctrl_dev *pctldev,
+ unsigned pin,
+ unsigned long *configs,
+ unsigned num_configs,
+ u32 *val,
+ u32 *mask)
+{
+ struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+ int i, j;
+ enum pin_config_param param;
+ u16 arg;
+
+ for (i = 0; i < num_configs; i++) {
+ param = pinconf_to_config_param(configs[i]);
+ arg = pinconf_to_config_argument(configs[i]);
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_PULL_UP:
+ for (j = 0; j < ARRAY_SIZE(bcm281xx_pullup_map); j++)
+ if (bcm281xx_pullup_map[j] == arg)
+ break;
+
+ if (j == ARRAY_SIZE(bcm281xx_pullup_map)) {
+ dev_err(pctldev->dev,
+ "Invalid pull-up value (%d) for pin %s "
+ "(%d). Valid values are 568, 720, 831, "
+ "1080, 1200, 1800, 2700 Ohms.\n",
+ arg, pdata->pins[pin].name, pin);
+ return -EINVAL;
+ }
+
+ bcm281xx_pin_update(val, mask, j+1,
+ BCM281XX_PIN_SHIFT(I2C, PULL_UP_STR),
+ BCM281XX_PIN_MASK(I2C, PULL_UP_STR));
+ break;
+
+ case PIN_CONFIG_BIAS_DISABLE:
+ bcm281xx_pin_update(val, mask, 0,
+ BCM281XX_PIN_SHIFT(I2C, PULL_UP_STR),
+ BCM281XX_PIN_MASK(I2C, PULL_UP_STR));
+ break;
+
+ case PIN_CONFIG_SLEW_RATE:
+ arg = (arg >= 1 ? 1 : 0);
+ bcm281xx_pin_update(val, mask, arg,
+ BCM281XX_PIN_SHIFT(I2C, SLEW),
+ BCM281XX_PIN_MASK(I2C, SLEW));
+ break;
+
+ case PIN_CONFIG_INPUT_ENABLE:
+ /* inversed since register is for input _disable_ */
+ arg = (arg >= 1 ? 0 : 1);
+ bcm281xx_pin_update(val, mask, arg,
+ BCM281XX_PIN_SHIFT(I2C, INPUT_DIS),
+ BCM281XX_PIN_MASK(I2C, INPUT_DIS));
+ break;
+
+ default:
+ dev_err(pctldev->dev,
+ "Unrecognized pin config %d for pin %s (%d).\n",
+ param, pdata->pins[pin].name, pin);
+ return -EINVAL;
+
+ } /* switch config */
+ } /* for each config */
+
+ return 0;
+}
+
+/* Goes through the configs and update register val/mask */
+static int bcm281xx_hdmi_pin_update(struct pinctrl_dev *pctldev,
+ unsigned pin,
+ unsigned long *configs,
+ unsigned num_configs,
+ u32 *val,
+ u32 *mask)
+{
+ struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+ int i;
+ enum pin_config_param param;
+ u16 arg;
+
+ for (i = 0; i < num_configs; i++) {
+ param = pinconf_to_config_param(configs[i]);
+ arg = pinconf_to_config_argument(configs[i]);
+
+ switch (param) {
+ case PIN_CONFIG_SLEW_RATE:
+ arg = (arg >= 1 ? 1 : 0);
+ bcm281xx_pin_update(val, mask, arg,
+ BCM281XX_PIN_SHIFT(HDMI, MODE),
+ BCM281XX_PIN_MASK(HDMI, MODE));
+ break;
+
+ case PIN_CONFIG_INPUT_ENABLE:
+ /* inversed since register is for input _disable_ */
+ arg = (arg >= 1 ? 0 : 1);
+ bcm281xx_pin_update(val, mask, arg,
+ BCM281XX_PIN_SHIFT(HDMI, INPUT_DIS),
+ BCM281XX_PIN_MASK(HDMI, INPUT_DIS));
+ break;
+
+ default:
+ dev_err(pctldev->dev,
+ "Unrecognized pin config %d for pin %s (%d).\n",
+ param, pdata->pins[pin].name, pin);
+ return -EINVAL;
+
+ } /* switch config */
+ } /* for each config */
+
+ return 0;
+}
+
+static int bcm281xx_pinctrl_pin_config_set(struct pinctrl_dev *pctldev,
+ unsigned pin,
+ unsigned long *configs,
+ unsigned num_configs)
+{
+ struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+ enum bcm281xx_pin_type pin_type;
+ u32 offset = 4 * pin;
+ u32 cfg_val, cfg_mask;
+ int rc;
+
+ cfg_val = 0;
+ cfg_mask = 0;
+ pin_type = pin_type_get(pctldev, pin);
+
+ /* Different pins have different configuration options */
+ switch (pin_type) {
+ case BCM281XX_PIN_TYPE_STD:
+ rc = bcm281xx_std_pin_update(pctldev, pin, configs,
+ num_configs, &cfg_val, &cfg_mask);
+ break;
+
+ case BCM281XX_PIN_TYPE_I2C:
+ rc = bcm281xx_i2c_pin_update(pctldev, pin, configs,
+ num_configs, &cfg_val, &cfg_mask);
+ break;
+
+ case BCM281XX_PIN_TYPE_HDMI:
+ rc = bcm281xx_hdmi_pin_update(pctldev, pin, configs,
+ num_configs, &cfg_val, &cfg_mask);
+ break;
+
+ default:
+ dev_err(pctldev->dev, "Unknown pin type for pin %s (%d).\n",
+ pdata->pins[pin].name, pin);
+ return -EINVAL;
+
+ } /* switch pin type */
+
+ if (rc)
+ return rc;
+
+ dev_dbg(pctldev->dev,
+ "%s(): Set pin %s (%d) with config 0x%x, mask 0x%x\n",
+ __func__, pdata->pins[pin].name, pin, cfg_val, cfg_mask);
+
+ rc = regmap_update_bits(pdata->regmap, offset, cfg_mask, cfg_val);
+ if (rc) {
+ dev_err(pctldev->dev,
+ "Error updating register for pin %s (%d).\n",
+ pdata->pins[pin].name, pin);
+ return rc;
+ }
+
+ return 0;
+}
+
+static struct pinconf_ops bcm281xx_pinctrl_pinconf_ops = {
+ .pin_config_get = bcm281xx_pinctrl_pin_config_get,
+ .pin_config_set = bcm281xx_pinctrl_pin_config_set,
+};
+
+static struct pinctrl_desc bcm281xx_pinctrl_desc = {
+ /* name, pins, npins members initialized in probe function */
+ .pctlops = &bcm281xx_pinctrl_ops,
+ .pmxops = &bcm281xx_pinctrl_pinmux_ops,
+ .confops = &bcm281xx_pinctrl_pinconf_ops,
+ .owner = THIS_MODULE,
+};
+
+int __init bcm281xx_pinctrl_probe(struct platform_device *pdev)
+{
+ struct bcm281xx_pinctrl_data *pdata = &bcm281xx_pinctrl;
+ struct resource *res;
+ struct pinctrl_dev *pctl;
+
+ /* So far We can assume there is only 1 bank of registers */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "Missing MEM resource\n");
+ return -ENODEV;
+ }
+
+ pdata->reg_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(pdata->reg_base)) {
+ dev_err(&pdev->dev, "Failed to ioremap MEM resource\n");
+ return -ENODEV;
+ }
+
+ /* Initialize the dynamic part of pinctrl_desc */
+ pdata->regmap = devm_regmap_init_mmio(&pdev->dev, pdata->reg_base,
+ &bcm281xx_pinctrl_regmap_config);
+ if (IS_ERR(pdata->regmap)) {
+ dev_err(&pdev->dev, "Regmap MMIO init failed.\n");
+ return -ENODEV;
+ }
+
+ bcm281xx_pinctrl_desc.name = dev_name(&pdev->dev);
+ bcm281xx_pinctrl_desc.pins = bcm281xx_pinctrl.pins;
+ bcm281xx_pinctrl_desc.npins = bcm281xx_pinctrl.npins;
+
+ pctl = pinctrl_register(&bcm281xx_pinctrl_desc,
+ &pdev->dev,
+ pdata);
+ if (!pctl) {
+ dev_err(&pdev->dev, "Failed to register pinctrl\n");
+ return -ENODEV;
+ }
+
+ platform_set_drvdata(pdev, pdata);
+
+ return 0;
+}
+
+static struct of_device_id bcm281xx_pinctrl_of_match[] = {
+ { .compatible = "brcm,bcm11351-pinctrl", },
+ { },
+};
+
+static struct platform_driver bcm281xx_pinctrl_driver = {
+ .driver = {
+ .name = "bcm281xx-pinctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = bcm281xx_pinctrl_of_match,
+ },
+};
+
+module_platform_driver_probe(bcm281xx_pinctrl_driver, bcm281xx_pinctrl_probe);
+
+MODULE_AUTHOR("Broadcom Corporation <bcm-kernel-feedback-list@broadcom.com>");
+MODULE_AUTHOR("Sherman Yin <syin@broadcom.com>");
+MODULE_DESCRIPTION("Broadcom BCM281xx pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-capri.c b/drivers/pinctrl/pinctrl-capri.c
deleted file mode 100644
index eb2500212147..000000000000
--- a/drivers/pinctrl/pinctrl-capri.c
+++ /dev/null
@@ -1,1454 +0,0 @@
-/*
- * Copyright (C) 2013 Broadcom Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation version 2.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
-#include <linux/pinctrl/pinmux.h>
-#include <linux/pinctrl/pinconf.h>
-#include <linux/pinctrl/pinconf-generic.h>
-#include <linux/regmap.h>
-#include <linux/slab.h>
-#include "core.h"
-#include "pinctrl-utils.h"
-
-/* Capri Pin Control Registers Definitions */
-
-/* Function Select bits are the same for all pin control registers */
-#define CAPRI_PIN_REG_F_SEL_MASK 0x0700
-#define CAPRI_PIN_REG_F_SEL_SHIFT 8
-
-/* Standard pin register */
-#define CAPRI_STD_PIN_REG_DRV_STR_MASK 0x0007
-#define CAPRI_STD_PIN_REG_DRV_STR_SHIFT 0
-#define CAPRI_STD_PIN_REG_INPUT_DIS_MASK 0x0008
-#define CAPRI_STD_PIN_REG_INPUT_DIS_SHIFT 3
-#define CAPRI_STD_PIN_REG_SLEW_MASK 0x0010
-#define CAPRI_STD_PIN_REG_SLEW_SHIFT 4
-#define CAPRI_STD_PIN_REG_PULL_UP_MASK 0x0020
-#define CAPRI_STD_PIN_REG_PULL_UP_SHIFT 5
-#define CAPRI_STD_PIN_REG_PULL_DN_MASK 0x0040
-#define CAPRI_STD_PIN_REG_PULL_DN_SHIFT 6
-#define CAPRI_STD_PIN_REG_HYST_MASK 0x0080
-#define CAPRI_STD_PIN_REG_HYST_SHIFT 7
-
-/* I2C pin register */
-#define CAPRI_I2C_PIN_REG_INPUT_DIS_MASK 0x0004
-#define CAPRI_I2C_PIN_REG_INPUT_DIS_SHIFT 2
-#define CAPRI_I2C_PIN_REG_SLEW_MASK 0x0008
-#define CAPRI_I2C_PIN_REG_SLEW_SHIFT 3
-#define CAPRI_I2C_PIN_REG_PULL_UP_STR_MASK 0x0070
-#define CAPRI_I2C_PIN_REG_PULL_UP_STR_SHIFT 4
-
-/* HDMI pin register */
-#define CAPRI_HDMI_PIN_REG_INPUT_DIS_MASK 0x0008
-#define CAPRI_HDMI_PIN_REG_INPUT_DIS_SHIFT 3
-#define CAPRI_HDMI_PIN_REG_MODE_MASK 0x0010
-#define CAPRI_HDMI_PIN_REG_MODE_SHIFT 4
-
-/**
- * capri_pin_type - types of pin register
- */
-enum capri_pin_type {
- CAPRI_PIN_TYPE_UNKNOWN = 0,
- CAPRI_PIN_TYPE_STD,
- CAPRI_PIN_TYPE_I2C,
- CAPRI_PIN_TYPE_HDMI,
-};
-
-static enum capri_pin_type std_pin = CAPRI_PIN_TYPE_STD;
-static enum capri_pin_type i2c_pin = CAPRI_PIN_TYPE_I2C;
-static enum capri_pin_type hdmi_pin = CAPRI_PIN_TYPE_HDMI;
-
-/**
- * capri_pin_function- define pin function
- */
-struct capri_pin_function {
- const char *name;
- const char * const *groups;
- const unsigned ngroups;
-};
-
-/**
- * capri_pinctrl_data - Broadcom-specific pinctrl data
- * @reg_base - base of pinctrl registers
- */
-struct capri_pinctrl_data {
- void __iomem *reg_base;
-
- /* List of all pins */
- const struct pinctrl_pin_desc *pins;
- const unsigned npins;
-
- const struct capri_pin_function *functions;
- const unsigned nfunctions;
-
- struct regmap *regmap;
-};
-
-/*
- * Pin number definition. The order here must be the same as defined in the
- * PADCTRLREG block in the RDB.
- */
-#define CAPRI_PIN_ADCSYNC 0
-#define CAPRI_PIN_BAT_RM 1
-#define CAPRI_PIN_BSC1_SCL 2
-#define CAPRI_PIN_BSC1_SDA 3
-#define CAPRI_PIN_BSC2_SCL 4
-#define CAPRI_PIN_BSC2_SDA 5
-#define CAPRI_PIN_CLASSGPWR 6
-#define CAPRI_PIN_CLK_CX8 7
-#define CAPRI_PIN_CLKOUT_0 8
-#define CAPRI_PIN_CLKOUT_1 9
-#define CAPRI_PIN_CLKOUT_2 10
-#define CAPRI_PIN_CLKOUT_3 11
-#define CAPRI_PIN_CLKREQ_IN_0 12
-#define CAPRI_PIN_CLKREQ_IN_1 13
-#define CAPRI_PIN_CWS_SYS_REQ1 14
-#define CAPRI_PIN_CWS_SYS_REQ2 15
-#define CAPRI_PIN_CWS_SYS_REQ3 16
-#define CAPRI_PIN_DIGMIC1_CLK 17
-#define CAPRI_PIN_DIGMIC1_DQ 18
-#define CAPRI_PIN_DIGMIC2_CLK 19
-#define CAPRI_PIN_DIGMIC2_DQ 20
-#define CAPRI_PIN_GPEN13 21
-#define CAPRI_PIN_GPEN14 22
-#define CAPRI_PIN_GPEN15 23
-#define CAPRI_PIN_GPIO00 24
-#define CAPRI_PIN_GPIO01 25
-#define CAPRI_PIN_GPIO02 26
-#define CAPRI_PIN_GPIO03 27
-#define CAPRI_PIN_GPIO04 28
-#define CAPRI_PIN_GPIO05 29
-#define CAPRI_PIN_GPIO06 30
-#define CAPRI_PIN_GPIO07 31
-#define CAPRI_PIN_GPIO08 32
-#define CAPRI_PIN_GPIO09 33
-#define CAPRI_PIN_GPIO10 34
-#define CAPRI_PIN_GPIO11 35
-#define CAPRI_PIN_GPIO12 36
-#define CAPRI_PIN_GPIO13 37
-#define CAPRI_PIN_GPIO14 38
-#define CAPRI_PIN_GPS_PABLANK 39
-#define CAPRI_PIN_GPS_TMARK 40
-#define CAPRI_PIN_HDMI_SCL 41
-#define CAPRI_PIN_HDMI_SDA 42
-#define CAPRI_PIN_IC_DM 43
-#define CAPRI_PIN_IC_DP 44
-#define CAPRI_PIN_KP_COL_IP_0 45
-#define CAPRI_PIN_KP_COL_IP_1 46
-#define CAPRI_PIN_KP_COL_IP_2 47
-#define CAPRI_PIN_KP_COL_IP_3 48
-#define CAPRI_PIN_KP_ROW_OP_0 49
-#define CAPRI_PIN_KP_ROW_OP_1 50
-#define CAPRI_PIN_KP_ROW_OP_2 51
-#define CAPRI_PIN_KP_ROW_OP_3 52
-#define CAPRI_PIN_LCD_B_0 53
-#define CAPRI_PIN_LCD_B_1 54
-#define CAPRI_PIN_LCD_B_2 55
-#define CAPRI_PIN_LCD_B_3 56
-#define CAPRI_PIN_LCD_B_4 57
-#define CAPRI_PIN_LCD_B_5 58
-#define CAPRI_PIN_LCD_B_6 59
-#define CAPRI_PIN_LCD_B_7 60
-#define CAPRI_PIN_LCD_G_0 61
-#define CAPRI_PIN_LCD_G_1 62
-#define CAPRI_PIN_LCD_G_2 63
-#define CAPRI_PIN_LCD_G_3 64
-#define CAPRI_PIN_LCD_G_4 65
-#define CAPRI_PIN_LCD_G_5 66
-#define CAPRI_PIN_LCD_G_6 67
-#define CAPRI_PIN_LCD_G_7 68
-#define CAPRI_PIN_LCD_HSYNC 69
-#define CAPRI_PIN_LCD_OE 70
-#define CAPRI_PIN_LCD_PCLK 71
-#define CAPRI_PIN_LCD_R_0 72
-#define CAPRI_PIN_LCD_R_1 73
-#define CAPRI_PIN_LCD_R_2 74
-#define CAPRI_PIN_LCD_R_3 75
-#define CAPRI_PIN_LCD_R_4 76
-#define CAPRI_PIN_LCD_R_5 77
-#define CAPRI_PIN_LCD_R_6 78
-#define CAPRI_PIN_LCD_R_7 79
-#define CAPRI_PIN_LCD_VSYNC 80
-#define CAPRI_PIN_MDMGPIO0 81
-#define CAPRI_PIN_MDMGPIO1 82
-#define CAPRI_PIN_MDMGPIO2 83
-#define CAPRI_PIN_MDMGPIO3 84
-#define CAPRI_PIN_MDMGPIO4 85
-#define CAPRI_PIN_MDMGPIO5 86
-#define CAPRI_PIN_MDMGPIO6 87
-#define CAPRI_PIN_MDMGPIO7 88
-#define CAPRI_PIN_MDMGPIO8 89
-#define CAPRI_PIN_MPHI_DATA_0 90
-#define CAPRI_PIN_MPHI_DATA_1 91
-#define CAPRI_PIN_MPHI_DATA_2 92
-#define CAPRI_PIN_MPHI_DATA_3 93
-#define CAPRI_PIN_MPHI_DATA_4 94
-#define CAPRI_PIN_MPHI_DATA_5 95
-#define CAPRI_PIN_MPHI_DATA_6 96
-#define CAPRI_PIN_MPHI_DATA_7 97
-#define CAPRI_PIN_MPHI_DATA_8 98
-#define CAPRI_PIN_MPHI_DATA_9 99
-#define CAPRI_PIN_MPHI_DATA_10 100
-#define CAPRI_PIN_MPHI_DATA_11 101
-#define CAPRI_PIN_MPHI_DATA_12 102
-#define CAPRI_PIN_MPHI_DATA_13 103
-#define CAPRI_PIN_MPHI_DATA_14 104
-#define CAPRI_PIN_MPHI_DATA_15 105
-#define CAPRI_PIN_MPHI_HA0 106
-#define CAPRI_PIN_MPHI_HAT0 107
-#define CAPRI_PIN_MPHI_HAT1 108
-#define CAPRI_PIN_MPHI_HCE0_N 109
-#define CAPRI_PIN_MPHI_HCE1_N 110
-#define CAPRI_PIN_MPHI_HRD_N 111
-#define CAPRI_PIN_MPHI_HWR_N 112
-#define CAPRI_PIN_MPHI_RUN0 113
-#define CAPRI_PIN_MPHI_RUN1 114
-#define CAPRI_PIN_MTX_SCAN_CLK 115
-#define CAPRI_PIN_MTX_SCAN_DATA 116
-#define CAPRI_PIN_NAND_AD_0 117
-#define CAPRI_PIN_NAND_AD_1 118
-#define CAPRI_PIN_NAND_AD_2 119
-#define CAPRI_PIN_NAND_AD_3 120
-#define CAPRI_PIN_NAND_AD_4 121
-#define CAPRI_PIN_NAND_AD_5 122
-#define CAPRI_PIN_NAND_AD_6 123
-#define CAPRI_PIN_NAND_AD_7 124
-#define CAPRI_PIN_NAND_ALE 125
-#define CAPRI_PIN_NAND_CEN_0 126
-#define CAPRI_PIN_NAND_CEN_1 127
-#define CAPRI_PIN_NAND_CLE 128
-#define CAPRI_PIN_NAND_OEN 129
-#define CAPRI_PIN_NAND_RDY_0 130
-#define CAPRI_PIN_NAND_RDY_1 131
-#define CAPRI_PIN_NAND_WEN 132
-#define CAPRI_PIN_NAND_WP 133
-#define CAPRI_PIN_PC1 134
-#define CAPRI_PIN_PC2 135
-#define CAPRI_PIN_PMU_INT 136
-#define CAPRI_PIN_PMU_SCL 137
-#define CAPRI_PIN_PMU_SDA 138
-#define CAPRI_PIN_RFST2G_MTSLOTEN3G 139
-#define CAPRI_PIN_RGMII_0_RX_CTL 140
-#define CAPRI_PIN_RGMII_0_RXC 141
-#define CAPRI_PIN_RGMII_0_RXD_0 142
-#define CAPRI_PIN_RGMII_0_RXD_1 143
-#define CAPRI_PIN_RGMII_0_RXD_2 144
-#define CAPRI_PIN_RGMII_0_RXD_3 145
-#define CAPRI_PIN_RGMII_0_TX_CTL 146
-#define CAPRI_PIN_RGMII_0_TXC 147
-#define CAPRI_PIN_RGMII_0_TXD_0 148
-#define CAPRI_PIN_RGMII_0_TXD_1 149
-#define CAPRI_PIN_RGMII_0_TXD_2 150
-#define CAPRI_PIN_RGMII_0_TXD_3 151
-#define CAPRI_PIN_RGMII_1_RX_CTL 152
-#define CAPRI_PIN_RGMII_1_RXC 153
-#define CAPRI_PIN_RGMII_1_RXD_0 154
-#define CAPRI_PIN_RGMII_1_RXD_1 155
-#define CAPRI_PIN_RGMII_1_RXD_2 156
-#define CAPRI_PIN_RGMII_1_RXD_3 157
-#define CAPRI_PIN_RGMII_1_TX_CTL 158
-#define CAPRI_PIN_RGMII_1_TXC 159
-#define CAPRI_PIN_RGMII_1_TXD_0 160
-#define CAPRI_PIN_RGMII_1_TXD_1 161
-#define CAPRI_PIN_RGMII_1_TXD_2 162
-#define CAPRI_PIN_RGMII_1_TXD_3 163
-#define CAPRI_PIN_RGMII_GPIO_0 164
-#define CAPRI_PIN_RGMII_GPIO_1 165
-#define CAPRI_PIN_RGMII_GPIO_2 166
-#define CAPRI_PIN_RGMII_GPIO_3 167
-#define CAPRI_PIN_RTXDATA2G_TXDATA3G1 168
-#define CAPRI_PIN_RTXEN2G_TXDATA3G2 169
-#define CAPRI_PIN_RXDATA3G0 170
-#define CAPRI_PIN_RXDATA3G1 171
-#define CAPRI_PIN_RXDATA3G2 172
-#define CAPRI_PIN_SDIO1_CLK 173
-#define CAPRI_PIN_SDIO1_CMD 174
-#define CAPRI_PIN_SDIO1_DATA_0 175
-#define CAPRI_PIN_SDIO1_DATA_1 176
-#define CAPRI_PIN_SDIO1_DATA_2 177
-#define CAPRI_PIN_SDIO1_DATA_3 178
-#define CAPRI_PIN_SDIO4_CLK 179
-#define CAPRI_PIN_SDIO4_CMD 180
-#define CAPRI_PIN_SDIO4_DATA_0 181
-#define CAPRI_PIN_SDIO4_DATA_1 182
-#define CAPRI_PIN_SDIO4_DATA_2 183
-#define CAPRI_PIN_SDIO4_DATA_3 184
-#define CAPRI_PIN_SIM_CLK 185
-#define CAPRI_PIN_SIM_DATA 186
-#define CAPRI_PIN_SIM_DET 187
-#define CAPRI_PIN_SIM_RESETN 188
-#define CAPRI_PIN_SIM2_CLK 189
-#define CAPRI_PIN_SIM2_DATA 190
-#define CAPRI_PIN_SIM2_DET 191
-#define CAPRI_PIN_SIM2_RESETN 192
-#define CAPRI_PIN_SRI_C 193
-#define CAPRI_PIN_SRI_D 194
-#define CAPRI_PIN_SRI_E 195
-#define CAPRI_PIN_SSP_EXTCLK 196
-#define CAPRI_PIN_SSP0_CLK 197
-#define CAPRI_PIN_SSP0_FS 198
-#define CAPRI_PIN_SSP0_RXD 199
-#define CAPRI_PIN_SSP0_TXD 200
-#define CAPRI_PIN_SSP2_CLK 201
-#define CAPRI_PIN_SSP2_FS_0 202
-#define CAPRI_PIN_SSP2_FS_1 203
-#define CAPRI_PIN_SSP2_FS_2 204
-#define CAPRI_PIN_SSP2_FS_3 205
-#define CAPRI_PIN_SSP2_RXD_0 206
-#define CAPRI_PIN_SSP2_RXD_1 207
-#define CAPRI_PIN_SSP2_TXD_0 208
-#define CAPRI_PIN_SSP2_TXD_1 209
-#define CAPRI_PIN_SSP3_CLK 210
-#define CAPRI_PIN_SSP3_FS 211
-#define CAPRI_PIN_SSP3_RXD 212
-#define CAPRI_PIN_SSP3_TXD 213
-#define CAPRI_PIN_SSP4_CLK 214
-#define CAPRI_PIN_SSP4_FS 215
-#define CAPRI_PIN_SSP4_RXD 216
-#define CAPRI_PIN_SSP4_TXD 217
-#define CAPRI_PIN_SSP5_CLK 218
-#define CAPRI_PIN_SSP5_FS 219
-#define CAPRI_PIN_SSP5_RXD 220
-#define CAPRI_PIN_SSP5_TXD 221
-#define CAPRI_PIN_SSP6_CLK 222
-#define CAPRI_PIN_SSP6_FS 223
-#define CAPRI_PIN_SSP6_RXD 224
-#define CAPRI_PIN_SSP6_TXD 225
-#define CAPRI_PIN_STAT_1 226
-#define CAPRI_PIN_STAT_2 227
-#define CAPRI_PIN_SYSCLKEN 228
-#define CAPRI_PIN_TRACECLK 229
-#define CAPRI_PIN_TRACEDT00 230
-#define CAPRI_PIN_TRACEDT01 231
-#define CAPRI_PIN_TRACEDT02 232
-#define CAPRI_PIN_TRACEDT03 233
-#define CAPRI_PIN_TRACEDT04 234
-#define CAPRI_PIN_TRACEDT05 235
-#define CAPRI_PIN_TRACEDT06 236
-#define CAPRI_PIN_TRACEDT07 237
-#define CAPRI_PIN_TRACEDT08 238
-#define CAPRI_PIN_TRACEDT09 239
-#define CAPRI_PIN_TRACEDT10 240
-#define CAPRI_PIN_TRACEDT11 241
-#define CAPRI_PIN_TRACEDT12 242
-#define CAPRI_PIN_TRACEDT13 243
-#define CAPRI_PIN_TRACEDT14 244
-#define CAPRI_PIN_TRACEDT15 245
-#define CAPRI_PIN_TXDATA3G0 246
-#define CAPRI_PIN_TXPWRIND 247
-#define CAPRI_PIN_UARTB1_UCTS 248
-#define CAPRI_PIN_UARTB1_URTS 249
-#define CAPRI_PIN_UARTB1_URXD 250
-#define CAPRI_PIN_UARTB1_UTXD 251
-#define CAPRI_PIN_UARTB2_URXD 252
-#define CAPRI_PIN_UARTB2_UTXD 253
-#define CAPRI_PIN_UARTB3_UCTS 254
-#define CAPRI_PIN_UARTB3_URTS 255
-#define CAPRI_PIN_UARTB3_URXD 256
-#define CAPRI_PIN_UARTB3_UTXD 257
-#define CAPRI_PIN_UARTB4_UCTS 258
-#define CAPRI_PIN_UARTB4_URTS 259
-#define CAPRI_PIN_UARTB4_URXD 260
-#define CAPRI_PIN_UARTB4_UTXD 261
-#define CAPRI_PIN_VC_CAM1_SCL 262
-#define CAPRI_PIN_VC_CAM1_SDA 263
-#define CAPRI_PIN_VC_CAM2_SCL 264
-#define CAPRI_PIN_VC_CAM2_SDA 265
-#define CAPRI_PIN_VC_CAM3_SCL 266
-#define CAPRI_PIN_VC_CAM3_SDA 267
-
-#define CAPRI_PIN_DESC(a, b, c) \
- { .number = a, .name = b, .drv_data = &c##_pin }
-
-/*
- * Pin description definition. The order here must be the same as defined in
- * the PADCTRLREG block in the RDB, since the pin number is used as an index
- * into this array.
- */
-static const struct pinctrl_pin_desc capri_pinctrl_pins[] = {
- CAPRI_PIN_DESC(CAPRI_PIN_ADCSYNC, "adcsync", std),
- CAPRI_PIN_DESC(CAPRI_PIN_BAT_RM, "bat_rm", std),
- CAPRI_PIN_DESC(CAPRI_PIN_BSC1_SCL, "bsc1_scl", i2c),
- CAPRI_PIN_DESC(CAPRI_PIN_BSC1_SDA, "bsc1_sda", i2c),
- CAPRI_PIN_DESC(CAPRI_PIN_BSC2_SCL, "bsc2_scl", i2c),
- CAPRI_PIN_DESC(CAPRI_PIN_BSC2_SDA, "bsc2_sda", i2c),
- CAPRI_PIN_DESC(CAPRI_PIN_CLASSGPWR, "classgpwr", std),
- CAPRI_PIN_DESC(CAPRI_PIN_CLK_CX8, "clk_cx8", std),
- CAPRI_PIN_DESC(CAPRI_PIN_CLKOUT_0, "clkout_0", std),
- CAPRI_PIN_DESC(CAPRI_PIN_CLKOUT_1, "clkout_1", std),
- CAPRI_PIN_DESC(CAPRI_PIN_CLKOUT_2, "clkout_2", std),
- CAPRI_PIN_DESC(CAPRI_PIN_CLKOUT_3, "clkout_3", std),
- CAPRI_PIN_DESC(CAPRI_PIN_CLKREQ_IN_0, "clkreq_in_0", std),
- CAPRI_PIN_DESC(CAPRI_PIN_CLKREQ_IN_1, "clkreq_in_1", std),
- CAPRI_PIN_DESC(CAPRI_PIN_CWS_SYS_REQ1, "cws_sys_req1", std),
- CAPRI_PIN_DESC(CAPRI_PIN_CWS_SYS_REQ2, "cws_sys_req2", std),
- CAPRI_PIN_DESC(CAPRI_PIN_CWS_SYS_REQ3, "cws_sys_req3", std),
- CAPRI_PIN_DESC(CAPRI_PIN_DIGMIC1_CLK, "digmic1_clk", std),
- CAPRI_PIN_DESC(CAPRI_PIN_DIGMIC1_DQ, "digmic1_dq", std),
- CAPRI_PIN_DESC(CAPRI_PIN_DIGMIC2_CLK, "digmic2_clk", std),
- CAPRI_PIN_DESC(CAPRI_PIN_DIGMIC2_DQ, "digmic2_dq", std),
- CAPRI_PIN_DESC(CAPRI_PIN_GPEN13, "gpen13", std),
- CAPRI_PIN_DESC(CAPRI_PIN_GPEN14, "gpen14", std),
- CAPRI_PIN_DESC(CAPRI_PIN_GPEN15, "gpen15", std),
- CAPRI_PIN_DESC(CAPRI_PIN_GPIO00, "gpio00", std),
- CAPRI_PIN_DESC(CAPRI_PIN_GPIO01, "gpio01", std),
- CAPRI_PIN_DESC(CAPRI_PIN_GPIO02, "gpio02", std),
- CAPRI_PIN_DESC(CAPRI_PIN_GPIO03, "gpio03", std),
- CAPRI_PIN_DESC(CAPRI_PIN_GPIO04, "gpio04", std),
- CAPRI_PIN_DESC(CAPRI_PIN_GPIO05, "gpio05", std),
- CAPRI_PIN_DESC(CAPRI_PIN_GPIO06, "gpio06", std),
- CAPRI_PIN_DESC(CAPRI_PIN_GPIO07, "gpio07", std),
- CAPRI_PIN_DESC(CAPRI_PIN_GPIO08, "gpio08", std),
- CAPRI_PIN_DESC(CAPRI_PIN_GPIO09, "gpio09", std),
- CAPRI_PIN_DESC(CAPRI_PIN_GPIO10, "gpio10", std),
- CAPRI_PIN_DESC(CAPRI_PIN_GPIO11, "gpio11", std),
- CAPRI_PIN_DESC(CAPRI_PIN_GPIO12, "gpio12", std),
- CAPRI_PIN_DESC(CAPRI_PIN_GPIO13, "gpio13", std),
- CAPRI_PIN_DESC(CAPRI_PIN_GPIO14, "gpio14", std),
- CAPRI_PIN_DESC(CAPRI_PIN_GPS_PABLANK, "gps_pablank", std),
- CAPRI_PIN_DESC(CAPRI_PIN_GPS_TMARK, "gps_tmark", std),
- CAPRI_PIN_DESC(CAPRI_PIN_HDMI_SCL, "hdmi_scl", hdmi),
- CAPRI_PIN_DESC(CAPRI_PIN_HDMI_SDA, "hdmi_sda", hdmi),
- CAPRI_PIN_DESC(CAPRI_PIN_IC_DM, "ic_dm", std),
- CAPRI_PIN_DESC(CAPRI_PIN_IC_DP, "ic_dp", std),
- CAPRI_PIN_DESC(CAPRI_PIN_KP_COL_IP_0, "kp_col_ip_0", std),
- CAPRI_PIN_DESC(CAPRI_PIN_KP_COL_IP_1, "kp_col_ip_1", std),
- CAPRI_PIN_DESC(CAPRI_PIN_KP_COL_IP_2, "kp_col_ip_2", std),
- CAPRI_PIN_DESC(CAPRI_PIN_KP_COL_IP_3, "kp_col_ip_3", std),
- CAPRI_PIN_DESC(CAPRI_PIN_KP_ROW_OP_0, "kp_row_op_0", std),
- CAPRI_PIN_DESC(CAPRI_PIN_KP_ROW_OP_1, "kp_row_op_1", std),
- CAPRI_PIN_DESC(CAPRI_PIN_KP_ROW_OP_2, "kp_row_op_2", std),
- CAPRI_PIN_DESC(CAPRI_PIN_KP_ROW_OP_3, "kp_row_op_3", std),
- CAPRI_PIN_DESC(CAPRI_PIN_LCD_B_0, "lcd_b_0", std),
- CAPRI_PIN_DESC(CAPRI_PIN_LCD_B_1, "lcd_b_1", std),
- CAPRI_PIN_DESC(CAPRI_PIN_LCD_B_2, "lcd_b_2", std),
- CAPRI_PIN_DESC(CAPRI_PIN_LCD_B_3, "lcd_b_3", std),
- CAPRI_PIN_DESC(CAPRI_PIN_LCD_B_4, "lcd_b_4", std),
- CAPRI_PIN_DESC(CAPRI_PIN_LCD_B_5, "lcd_b_5", std),
- CAPRI_PIN_DESC(CAPRI_PIN_LCD_B_6, "lcd_b_6", std),
- CAPRI_PIN_DESC(CAPRI_PIN_LCD_B_7, "lcd_b_7", std),
- CAPRI_PIN_DESC(CAPRI_PIN_LCD_G_0, "lcd_g_0", std),
- CAPRI_PIN_DESC(CAPRI_PIN_LCD_G_1, "lcd_g_1", std),
- CAPRI_PIN_DESC(CAPRI_PIN_LCD_G_2, "lcd_g_2", std),
- CAPRI_PIN_DESC(CAPRI_PIN_LCD_G_3, "lcd_g_3", std),
- CAPRI_PIN_DESC(CAPRI_PIN_LCD_G_4, "lcd_g_4", std),
- CAPRI_PIN_DESC(CAPRI_PIN_LCD_G_5, "lcd_g_5", std),
- CAPRI_PIN_DESC(CAPRI_PIN_LCD_G_6, "lcd_g_6", std),
- CAPRI_PIN_DESC(CAPRI_PIN_LCD_G_7, "lcd_g_7", std),
- CAPRI_PIN_DESC(CAPRI_PIN_LCD_HSYNC, "lcd_hsync", std),
- CAPRI_PIN_DESC(CAPRI_PIN_LCD_OE, "lcd_oe", std),
- CAPRI_PIN_DESC(CAPRI_PIN_LCD_PCLK, "lcd_pclk", std),
- CAPRI_PIN_DESC(CAPRI_PIN_LCD_R_0, "lcd_r_0", std),
- CAPRI_PIN_DESC(CAPRI_PIN_LCD_R_1, "lcd_r_1", std),
- CAPRI_PIN_DESC(CAPRI_PIN_LCD_R_2, "lcd_r_2", std),
- CAPRI_PIN_DESC(CAPRI_PIN_LCD_R_3, "lcd_r_3", std),
- CAPRI_PIN_DESC(CAPRI_PIN_LCD_R_4, "lcd_r_4", std),
- CAPRI_PIN_DESC(CAPRI_PIN_LCD_R_5, "lcd_r_5", std),
- CAPRI_PIN_DESC(CAPRI_PIN_LCD_R_6, "lcd_r_6", std),
- CAPRI_PIN_DESC(CAPRI_PIN_LCD_R_7, "lcd_r_7", std),
- CAPRI_PIN_DESC(CAPRI_PIN_LCD_VSYNC, "lcd_vsync", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MDMGPIO0, "mdmgpio0", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MDMGPIO1, "mdmgpio1", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MDMGPIO2, "mdmgpio2", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MDMGPIO3, "mdmgpio3", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MDMGPIO4, "mdmgpio4", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MDMGPIO5, "mdmgpio5", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MDMGPIO6, "mdmgpio6", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MDMGPIO7, "mdmgpio7", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MDMGPIO8, "mdmgpio8", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MPHI_DATA_0, "mphi_data_0", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MPHI_DATA_1, "mphi_data_1", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MPHI_DATA_2, "mphi_data_2", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MPHI_DATA_3, "mphi_data_3", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MPHI_DATA_4, "mphi_data_4", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MPHI_DATA_5, "mphi_data_5", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MPHI_DATA_6, "mphi_data_6", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MPHI_DATA_7, "mphi_data_7", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MPHI_DATA_8, "mphi_data_8", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MPHI_DATA_9, "mphi_data_9", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MPHI_DATA_10, "mphi_data_10", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MPHI_DATA_11, "mphi_data_11", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MPHI_DATA_12, "mphi_data_12", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MPHI_DATA_13, "mphi_data_13", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MPHI_DATA_14, "mphi_data_14", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MPHI_DATA_15, "mphi_data_15", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MPHI_HA0, "mphi_ha0", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MPHI_HAT0, "mphi_hat0", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MPHI_HAT1, "mphi_hat1", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MPHI_HCE0_N, "mphi_hce0_n", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MPHI_HCE1_N, "mphi_hce1_n", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MPHI_HRD_N, "mphi_hrd_n", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MPHI_HWR_N, "mphi_hwr_n", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MPHI_RUN0, "mphi_run0", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MPHI_RUN1, "mphi_run1", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MTX_SCAN_CLK, "mtx_scan_clk", std),
- CAPRI_PIN_DESC(CAPRI_PIN_MTX_SCAN_DATA, "mtx_scan_data", std),
- CAPRI_PIN_DESC(CAPRI_PIN_NAND_AD_0, "nand_ad_0", std),
- CAPRI_PIN_DESC(CAPRI_PIN_NAND_AD_1, "nand_ad_1", std),
- CAPRI_PIN_DESC(CAPRI_PIN_NAND_AD_2, "nand_ad_2", std),
- CAPRI_PIN_DESC(CAPRI_PIN_NAND_AD_3, "nand_ad_3", std),
- CAPRI_PIN_DESC(CAPRI_PIN_NAND_AD_4, "nand_ad_4", std),
- CAPRI_PIN_DESC(CAPRI_PIN_NAND_AD_5, "nand_ad_5", std),
- CAPRI_PIN_DESC(CAPRI_PIN_NAND_AD_6, "nand_ad_6", std),
- CAPRI_PIN_DESC(CAPRI_PIN_NAND_AD_7, "nand_ad_7", std),
- CAPRI_PIN_DESC(CAPRI_PIN_NAND_ALE, "nand_ale", std),
- CAPRI_PIN_DESC(CAPRI_PIN_NAND_CEN_0, "nand_cen_0", std),
- CAPRI_PIN_DESC(CAPRI_PIN_NAND_CEN_1, "nand_cen_1", std),
- CAPRI_PIN_DESC(CAPRI_PIN_NAND_CLE, "nand_cle", std),
- CAPRI_PIN_DESC(CAPRI_PIN_NAND_OEN, "nand_oen", std),
- CAPRI_PIN_DESC(CAPRI_PIN_NAND_RDY_0, "nand_rdy_0", std),
- CAPRI_PIN_DESC(CAPRI_PIN_NAND_RDY_1, "nand_rdy_1", std),
- CAPRI_PIN_DESC(CAPRI_PIN_NAND_WEN, "nand_wen", std),
- CAPRI_PIN_DESC(CAPRI_PIN_NAND_WP, "nand_wp", std),
- CAPRI_PIN_DESC(CAPRI_PIN_PC1, "pc1", std),
- CAPRI_PIN_DESC(CAPRI_PIN_PC2, "pc2", std),
- CAPRI_PIN_DESC(CAPRI_PIN_PMU_INT, "pmu_int", std),
- CAPRI_PIN_DESC(CAPRI_PIN_PMU_SCL, "pmu_scl", i2c),
- CAPRI_PIN_DESC(CAPRI_PIN_PMU_SDA, "pmu_sda", i2c),
- CAPRI_PIN_DESC(CAPRI_PIN_RFST2G_MTSLOTEN3G, "rfst2g_mtsloten3g", std),
- CAPRI_PIN_DESC(CAPRI_PIN_RGMII_0_RX_CTL, "rgmii_0_rx_ctl", std),
- CAPRI_PIN_DESC(CAPRI_PIN_RGMII_0_RXC, "rgmii_0_rxc", std),
- CAPRI_PIN_DESC(CAPRI_PIN_RGMII_0_RXD_0, "rgmii_0_rxd_0", std),
- CAPRI_PIN_DESC(CAPRI_PIN_RGMII_0_RXD_1, "rgmii_0_rxd_1", std),
- CAPRI_PIN_DESC(CAPRI_PIN_RGMII_0_RXD_2, "rgmii_0_rxd_2", std),
- CAPRI_PIN_DESC(CAPRI_PIN_RGMII_0_RXD_3, "rgmii_0_rxd_3", std),
- CAPRI_PIN_DESC(CAPRI_PIN_RGMII_0_TX_CTL, "rgmii_0_tx_ctl", std),
- CAPRI_PIN_DESC(CAPRI_PIN_RGMII_0_TXC, "rgmii_0_txc", std),
- CAPRI_PIN_DESC(CAPRI_PIN_RGMII_0_TXD_0, "rgmii_0_txd_0", std),
- CAPRI_PIN_DESC(CAPRI_PIN_RGMII_0_TXD_1, "rgmii_0_txd_1", std),
- CAPRI_PIN_DESC(CAPRI_PIN_RGMII_0_TXD_2, "rgmii_0_txd_2", std),
- CAPRI_PIN_DESC(CAPRI_PIN_RGMII_0_TXD_3, "rgmii_0_txd_3", std),
- CAPRI_PIN_DESC(CAPRI_PIN_RGMII_1_RX_CTL, "rgmii_1_rx_ctl", std),
- CAPRI_PIN_DESC(CAPRI_PIN_RGMII_1_RXC, "rgmii_1_rxc", std),
- CAPRI_PIN_DESC(CAPRI_PIN_RGMII_1_RXD_0, "rgmii_1_rxd_0", std),
- CAPRI_PIN_DESC(CAPRI_PIN_RGMII_1_RXD_1, "rgmii_1_rxd_1", std),
- CAPRI_PIN_DESC(CAPRI_PIN_RGMII_1_RXD_2, "rgmii_1_rxd_2", std),
- CAPRI_PIN_DESC(CAPRI_PIN_RGMII_1_RXD_3, "rgmii_1_rxd_3", std),
- CAPRI_PIN_DESC(CAPRI_PIN_RGMII_1_TX_CTL, "rgmii_1_tx_ctl", std),
- CAPRI_PIN_DESC(CAPRI_PIN_RGMII_1_TXC, "rgmii_1_txc", std),
- CAPRI_PIN_DESC(CAPRI_PIN_RGMII_1_TXD_0, "rgmii_1_txd_0", std),
- CAPRI_PIN_DESC(CAPRI_PIN_RGMII_1_TXD_1, "rgmii_1_txd_1", std),
- CAPRI_PIN_DESC(CAPRI_PIN_RGMII_1_TXD_2, "rgmii_1_txd_2", std),
- CAPRI_PIN_DESC(CAPRI_PIN_RGMII_1_TXD_3, "rgmii_1_txd_3", std),
- CAPRI_PIN_DESC(CAPRI_PIN_RGMII_GPIO_0, "rgmii_gpio_0", std),
- CAPRI_PIN_DESC(CAPRI_PIN_RGMII_GPIO_1, "rgmii_gpio_1", std),
- CAPRI_PIN_DESC(CAPRI_PIN_RGMII_GPIO_2, "rgmii_gpio_2", std),
- CAPRI_PIN_DESC(CAPRI_PIN_RGMII_GPIO_3, "rgmii_gpio_3", std),
- CAPRI_PIN_DESC(CAPRI_PIN_RTXDATA2G_TXDATA3G1, "rtxdata2g_txdata3g1",
- std),
- CAPRI_PIN_DESC(CAPRI_PIN_RTXEN2G_TXDATA3G2, "rtxen2g_txdata3g2", std),
- CAPRI_PIN_DESC(CAPRI_PIN_RXDATA3G0, "rxdata3g0", std),
- CAPRI_PIN_DESC(CAPRI_PIN_RXDATA3G1, "rxdata3g1", std),
- CAPRI_PIN_DESC(CAPRI_PIN_RXDATA3G2, "rxdata3g2", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SDIO1_CLK, "sdio1_clk", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SDIO1_CMD, "sdio1_cmd", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SDIO1_DATA_0, "sdio1_data_0", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SDIO1_DATA_1, "sdio1_data_1", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SDIO1_DATA_2, "sdio1_data_2", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SDIO1_DATA_3, "sdio1_data_3", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SDIO4_CLK, "sdio4_clk", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SDIO4_CMD, "sdio4_cmd", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SDIO4_DATA_0, "sdio4_data_0", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SDIO4_DATA_1, "sdio4_data_1", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SDIO4_DATA_2, "sdio4_data_2", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SDIO4_DATA_3, "sdio4_data_3", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SIM_CLK, "sim_clk", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SIM_DATA, "sim_data", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SIM_DET, "sim_det", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SIM_RESETN, "sim_resetn", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SIM2_CLK, "sim2_clk", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SIM2_DATA, "sim2_data", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SIM2_DET, "sim2_det", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SIM2_RESETN, "sim2_resetn", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SRI_C, "sri_c", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SRI_D, "sri_d", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SRI_E, "sri_e", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SSP_EXTCLK, "ssp_extclk", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SSP0_CLK, "ssp0_clk", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SSP0_FS, "ssp0_fs", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SSP0_RXD, "ssp0_rxd", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SSP0_TXD, "ssp0_txd", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SSP2_CLK, "ssp2_clk", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SSP2_FS_0, "ssp2_fs_0", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SSP2_FS_1, "ssp2_fs_1", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SSP2_FS_2, "ssp2_fs_2", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SSP2_FS_3, "ssp2_fs_3", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SSP2_RXD_0, "ssp2_rxd_0", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SSP2_RXD_1, "ssp2_rxd_1", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SSP2_TXD_0, "ssp2_txd_0", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SSP2_TXD_1, "ssp2_txd_1", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SSP3_CLK, "ssp3_clk", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SSP3_FS, "ssp3_fs", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SSP3_RXD, "ssp3_rxd", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SSP3_TXD, "ssp3_txd", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SSP4_CLK, "ssp4_clk", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SSP4_FS, "ssp4_fs", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SSP4_RXD, "ssp4_rxd", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SSP4_TXD, "ssp4_txd", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SSP5_CLK, "ssp5_clk", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SSP5_FS, "ssp5_fs", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SSP5_RXD, "ssp5_rxd", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SSP5_TXD, "ssp5_txd", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SSP6_CLK, "ssp6_clk", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SSP6_FS, "ssp6_fs", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SSP6_RXD, "ssp6_rxd", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SSP6_TXD, "ssp6_txd", std),
- CAPRI_PIN_DESC(CAPRI_PIN_STAT_1, "stat_1", std),
- CAPRI_PIN_DESC(CAPRI_PIN_STAT_2, "stat_2", std),
- CAPRI_PIN_DESC(CAPRI_PIN_SYSCLKEN, "sysclken", std),
- CAPRI_PIN_DESC(CAPRI_PIN_TRACECLK, "traceclk", std),
- CAPRI_PIN_DESC(CAPRI_PIN_TRACEDT00, "tracedt00", std),
- CAPRI_PIN_DESC(CAPRI_PIN_TRACEDT01, "tracedt01", std),
- CAPRI_PIN_DESC(CAPRI_PIN_TRACEDT02, "tracedt02", std),
- CAPRI_PIN_DESC(CAPRI_PIN_TRACEDT03, "tracedt03", std),
- CAPRI_PIN_DESC(CAPRI_PIN_TRACEDT04, "tracedt04", std),
- CAPRI_PIN_DESC(CAPRI_PIN_TRACEDT05, "tracedt05", std),
- CAPRI_PIN_DESC(CAPRI_PIN_TRACEDT06, "tracedt06", std),
- CAPRI_PIN_DESC(CAPRI_PIN_TRACEDT07, "tracedt07", std),
- CAPRI_PIN_DESC(CAPRI_PIN_TRACEDT08, "tracedt08", std),
- CAPRI_PIN_DESC(CAPRI_PIN_TRACEDT09, "tracedt09", std),
- CAPRI_PIN_DESC(CAPRI_PIN_TRACEDT10, "tracedt10", std),
- CAPRI_PIN_DESC(CAPRI_PIN_TRACEDT11, "tracedt11", std),
- CAPRI_PIN_DESC(CAPRI_PIN_TRACEDT12, "tracedt12", std),
- CAPRI_PIN_DESC(CAPRI_PIN_TRACEDT13, "tracedt13", std),
- CAPRI_PIN_DESC(CAPRI_PIN_TRACEDT14, "tracedt14", std),
- CAPRI_PIN_DESC(CAPRI_PIN_TRACEDT15, "tracedt15", std),
- CAPRI_PIN_DESC(CAPRI_PIN_TXDATA3G0, "txdata3g0", std),
- CAPRI_PIN_DESC(CAPRI_PIN_TXPWRIND, "txpwrind", std),
- CAPRI_PIN_DESC(CAPRI_PIN_UARTB1_UCTS, "uartb1_ucts", std),
- CAPRI_PIN_DESC(CAPRI_PIN_UARTB1_URTS, "uartb1_urts", std),
- CAPRI_PIN_DESC(CAPRI_PIN_UARTB1_URXD, "uartb1_urxd", std),
- CAPRI_PIN_DESC(CAPRI_PIN_UARTB1_UTXD, "uartb1_utxd", std),
- CAPRI_PIN_DESC(CAPRI_PIN_UARTB2_URXD, "uartb2_urxd", std),
- CAPRI_PIN_DESC(CAPRI_PIN_UARTB2_UTXD, "uartb2_utxd", std),
- CAPRI_PIN_DESC(CAPRI_PIN_UARTB3_UCTS, "uartb3_ucts", std),
- CAPRI_PIN_DESC(CAPRI_PIN_UARTB3_URTS, "uartb3_urts", std),
- CAPRI_PIN_DESC(CAPRI_PIN_UARTB3_URXD, "uartb3_urxd", std),
- CAPRI_PIN_DESC(CAPRI_PIN_UARTB3_UTXD, "uartb3_utxd", std),
- CAPRI_PIN_DESC(CAPRI_PIN_UARTB4_UCTS, "uartb4_ucts", std),
- CAPRI_PIN_DESC(CAPRI_PIN_UARTB4_URTS, "uartb4_urts", std),
- CAPRI_PIN_DESC(CAPRI_PIN_UARTB4_URXD, "uartb4_urxd", std),
- CAPRI_PIN_DESC(CAPRI_PIN_UARTB4_UTXD, "uartb4_utxd", std),
- CAPRI_PIN_DESC(CAPRI_PIN_VC_CAM1_SCL, "vc_cam1_scl", i2c),
- CAPRI_PIN_DESC(CAPRI_PIN_VC_CAM1_SDA, "vc_cam1_sda", i2c),
- CAPRI_PIN_DESC(CAPRI_PIN_VC_CAM2_SCL, "vc_cam2_scl", i2c),
- CAPRI_PIN_DESC(CAPRI_PIN_VC_CAM2_SDA, "vc_cam2_sda", i2c),
- CAPRI_PIN_DESC(CAPRI_PIN_VC_CAM3_SCL, "vc_cam3_scl", i2c),
- CAPRI_PIN_DESC(CAPRI_PIN_VC_CAM3_SDA, "vc_cam3_sda", i2c),
-};
-
-static const char * const capri_alt_groups[] = {
- "adcsync",
- "bat_rm",
- "bsc1_scl",
- "bsc1_sda",
- "bsc2_scl",
- "bsc2_sda",
- "classgpwr",
- "clk_cx8",
- "clkout_0",
- "clkout_1",
- "clkout_2",
- "clkout_3",
- "clkreq_in_0",
- "clkreq_in_1",
- "cws_sys_req1",
- "cws_sys_req2",
- "cws_sys_req3",
- "digmic1_clk",
- "digmic1_dq",
- "digmic2_clk",
- "digmic2_dq",
- "gpen13",
- "gpen14",
- "gpen15",
- "gpio00",
- "gpio01",
- "gpio02",
- "gpio03",
- "gpio04",
- "gpio05",
- "gpio06",
- "gpio07",
- "gpio08",
- "gpio09",
- "gpio10",
- "gpio11",
- "gpio12",
- "gpio13",
- "gpio14",
- "gps_pablank",
- "gps_tmark",
- "hdmi_scl",
- "hdmi_sda",
- "ic_dm",
- "ic_dp",
- "kp_col_ip_0",
- "kp_col_ip_1",
- "kp_col_ip_2",
- "kp_col_ip_3",
- "kp_row_op_0",
- "kp_row_op_1",
- "kp_row_op_2",
- "kp_row_op_3",
- "lcd_b_0",
- "lcd_b_1",
- "lcd_b_2",
- "lcd_b_3",
- "lcd_b_4",
- "lcd_b_5",
- "lcd_b_6",
- "lcd_b_7",
- "lcd_g_0",
- "lcd_g_1",
- "lcd_g_2",
- "lcd_g_3",
- "lcd_g_4",
- "lcd_g_5",
- "lcd_g_6",
- "lcd_g_7",
- "lcd_hsync",
- "lcd_oe",
- "lcd_pclk",
- "lcd_r_0",
- "lcd_r_1",
- "lcd_r_2",
- "lcd_r_3",
- "lcd_r_4",
- "lcd_r_5",
- "lcd_r_6",
- "lcd_r_7",
- "lcd_vsync",
- "mdmgpio0",
- "mdmgpio1",
- "mdmgpio2",
- "mdmgpio3",
- "mdmgpio4",
- "mdmgpio5",
- "mdmgpio6",
- "mdmgpio7",
- "mdmgpio8",
- "mphi_data_0",
- "mphi_data_1",
- "mphi_data_2",
- "mphi_data_3",
- "mphi_data_4",
- "mphi_data_5",
- "mphi_data_6",
- "mphi_data_7",
- "mphi_data_8",
- "mphi_data_9",
- "mphi_data_10",
- "mphi_data_11",
- "mphi_data_12",
- "mphi_data_13",
- "mphi_data_14",
- "mphi_data_15",
- "mphi_ha0",
- "mphi_hat0",
- "mphi_hat1",
- "mphi_hce0_n",
- "mphi_hce1_n",
- "mphi_hrd_n",
- "mphi_hwr_n",
- "mphi_run0",
- "mphi_run1",
- "mtx_scan_clk",
- "mtx_scan_data",
- "nand_ad_0",
- "nand_ad_1",
- "nand_ad_2",
- "nand_ad_3",
- "nand_ad_4",
- "nand_ad_5",
- "nand_ad_6",
- "nand_ad_7",
- "nand_ale",
- "nand_cen_0",
- "nand_cen_1",
- "nand_cle",
- "nand_oen",
- "nand_rdy_0",
- "nand_rdy_1",
- "nand_wen",
- "nand_wp",
- "pc1",
- "pc2",
- "pmu_int",
- "pmu_scl",
- "pmu_sda",
- "rfst2g_mtsloten3g",
- "rgmii_0_rx_ctl",
- "rgmii_0_rxc",
- "rgmii_0_rxd_0",
- "rgmii_0_rxd_1",
- "rgmii_0_rxd_2",
- "rgmii_0_rxd_3",
- "rgmii_0_tx_ctl",
- "rgmii_0_txc",
- "rgmii_0_txd_0",
- "rgmii_0_txd_1",
- "rgmii_0_txd_2",
- "rgmii_0_txd_3",
- "rgmii_1_rx_ctl",
- "rgmii_1_rxc",
- "rgmii_1_rxd_0",
- "rgmii_1_rxd_1",
- "rgmii_1_rxd_2",
- "rgmii_1_rxd_3",
- "rgmii_1_tx_ctl",
- "rgmii_1_txc",
- "rgmii_1_txd_0",
- "rgmii_1_txd_1",
- "rgmii_1_txd_2",
- "rgmii_1_txd_3",
- "rgmii_gpio_0",
- "rgmii_gpio_1",
- "rgmii_gpio_2",
- "rgmii_gpio_3",
- "rtxdata2g_txdata3g1",
- "rtxen2g_txdata3g2",
- "rxdata3g0",
- "rxdata3g1",
- "rxdata3g2",
- "sdio1_clk",
- "sdio1_cmd",
- "sdio1_data_0",
- "sdio1_data_1",
- "sdio1_data_2",
- "sdio1_data_3",
- "sdio4_clk",
- "sdio4_cmd",
- "sdio4_data_0",
- "sdio4_data_1",
- "sdio4_data_2",
- "sdio4_data_3",
- "sim_clk",
- "sim_data",
- "sim_det",
- "sim_resetn",
- "sim2_clk",
- "sim2_data",
- "sim2_det",
- "sim2_resetn",
- "sri_c",
- "sri_d",
- "sri_e",
- "ssp_extclk",
- "ssp0_clk",
- "ssp0_fs",
- "ssp0_rxd",
- "ssp0_txd",
- "ssp2_clk",
- "ssp2_fs_0",
- "ssp2_fs_1",
- "ssp2_fs_2",
- "ssp2_fs_3",
- "ssp2_rxd_0",
- "ssp2_rxd_1",
- "ssp2_txd_0",
- "ssp2_txd_1",
- "ssp3_clk",
- "ssp3_fs",
- "ssp3_rxd",
- "ssp3_txd",
- "ssp4_clk",
- "ssp4_fs",
- "ssp4_rxd",
- "ssp4_txd",
- "ssp5_clk",
- "ssp5_fs",
- "ssp5_rxd",
- "ssp5_txd",
- "ssp6_clk",
- "ssp6_fs",
- "ssp6_rxd",
- "ssp6_txd",
- "stat_1",
- "stat_2",
- "sysclken",
- "traceclk",
- "tracedt00",
- "tracedt01",
- "tracedt02",
- "tracedt03",
- "tracedt04",
- "tracedt05",
- "tracedt06",
- "tracedt07",
- "tracedt08",
- "tracedt09",
- "tracedt10",
- "tracedt11",
- "tracedt12",
- "tracedt13",
- "tracedt14",
- "tracedt15",
- "txdata3g0",
- "txpwrind",
- "uartb1_ucts",
- "uartb1_urts",
- "uartb1_urxd",
- "uartb1_utxd",
- "uartb2_urxd",
- "uartb2_utxd",
- "uartb3_ucts",
- "uartb3_urts",
- "uartb3_urxd",
- "uartb3_utxd",
- "uartb4_ucts",
- "uartb4_urts",
- "uartb4_urxd",
- "uartb4_utxd",
- "vc_cam1_scl",
- "vc_cam1_sda",
- "vc_cam2_scl",
- "vc_cam2_sda",
- "vc_cam3_scl",
- "vc_cam3_sda",
-};
-
-/* Every pin can implement all ALT1-ALT4 functions */
-#define CAPRI_PIN_FUNCTION(fcn_name) \
-{ \
- .name = #fcn_name, \
- .groups = capri_alt_groups, \
- .ngroups = ARRAY_SIZE(capri_alt_groups), \
-}
-
-static const struct capri_pin_function capri_functions[] = {
- CAPRI_PIN_FUNCTION(alt1),
- CAPRI_PIN_FUNCTION(alt2),
- CAPRI_PIN_FUNCTION(alt3),
- CAPRI_PIN_FUNCTION(alt4),
-};
-
-static struct capri_pinctrl_data capri_pinctrl = {
- .pins = capri_pinctrl_pins,
- .npins = ARRAY_SIZE(capri_pinctrl_pins),
- .functions = capri_functions,
- .nfunctions = ARRAY_SIZE(capri_functions),
-};
-
-static inline enum capri_pin_type pin_type_get(struct pinctrl_dev *pctldev,
- unsigned pin)
-{
- struct capri_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
-
- if (pin >= pdata->npins)
- return CAPRI_PIN_TYPE_UNKNOWN;
-
- return *(enum capri_pin_type *)(pdata->pins[pin].drv_data);
-}
-
-#define CAPRI_PIN_SHIFT(type, param) \
- (CAPRI_ ## type ## _PIN_REG_ ## param ## _SHIFT)
-
-#define CAPRI_PIN_MASK(type, param) \
- (CAPRI_ ## type ## _PIN_REG_ ## param ## _MASK)
-
-/*
- * This helper function is used to build up the value and mask used to write to
- * a pin register, but does not actually write to the register.
- */
-static inline void capri_pin_update(u32 *reg_val, u32 *reg_mask, u32 param_val,
- u32 param_shift, u32 param_mask)
-{
- *reg_val &= ~param_mask;
- *reg_val |= (param_val << param_shift) & param_mask;
- *reg_mask |= param_mask;
-}
-
-static struct regmap_config capri_pinctrl_regmap_config = {
- .reg_bits = 32,
- .reg_stride = 4,
- .val_bits = 32,
- .max_register = CAPRI_PIN_VC_CAM3_SDA,
-};
-
-static int capri_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
-{
- struct capri_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
-
- return pdata->npins;
-}
-
-static const char *capri_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
- unsigned group)
-{
- struct capri_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
-
- return pdata->pins[group].name;
-}
-
-static int capri_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
- unsigned group,
- const unsigned **pins,
- unsigned *num_pins)
-{
- struct capri_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
-
- *pins = &pdata->pins[group].number;
- *num_pins = 1;
-
- return 0;
-}
-
-static void capri_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
- struct seq_file *s,
- unsigned offset)
-{
- seq_printf(s, " %s", dev_name(pctldev->dev));
-}
-
-static struct pinctrl_ops capri_pinctrl_ops = {
- .get_groups_count = capri_pinctrl_get_groups_count,
- .get_group_name = capri_pinctrl_get_group_name,
- .get_group_pins = capri_pinctrl_get_group_pins,
- .pin_dbg_show = capri_pinctrl_pin_dbg_show,
- .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
- .dt_free_map = pinctrl_utils_dt_free_map,
-};
-
-static int capri_pinctrl_get_fcns_count(struct pinctrl_dev *pctldev)
-{
- struct capri_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
-
- return pdata->nfunctions;
-}
-
-static const char *capri_pinctrl_get_fcn_name(struct pinctrl_dev *pctldev,
- unsigned function)
-{
- struct capri_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
-
- return pdata->functions[function].name;
-}
-
-static int capri_pinctrl_get_fcn_groups(struct pinctrl_dev *pctldev,
- unsigned function,
- const char * const **groups,
- unsigned * const num_groups)
-{
- struct capri_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
-
- *groups = pdata->functions[function].groups;
- *num_groups = pdata->functions[function].ngroups;
-
- return 0;
-}
-
-static int capri_pinmux_enable(struct pinctrl_dev *pctldev,
- unsigned function,
- unsigned group)
-{
- struct capri_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
- const struct capri_pin_function *f = &pdata->functions[function];
- u32 offset = 4 * pdata->pins[group].number;
- int rc = 0;
-
- dev_dbg(pctldev->dev,
- "%s(): Enable function %s (%d) of pin %s (%d) @offset 0x%x.\n",
- __func__, f->name, function, pdata->pins[group].name,
- pdata->pins[group].number, offset);
-
- rc = regmap_update_bits(pdata->regmap, offset, CAPRI_PIN_REG_F_SEL_MASK,
- function << CAPRI_PIN_REG_F_SEL_SHIFT);
- if (rc)
- dev_err(pctldev->dev,
- "Error updating register for pin %s (%d).\n",
- pdata->pins[group].name, pdata->pins[group].number);
-
- return rc;
-}
-
-static struct pinmux_ops capri_pinctrl_pinmux_ops = {
- .get_functions_count = capri_pinctrl_get_fcns_count,
- .get_function_name = capri_pinctrl_get_fcn_name,
- .get_function_groups = capri_pinctrl_get_fcn_groups,
- .enable = capri_pinmux_enable,
-};
-
-static int capri_pinctrl_pin_config_get(struct pinctrl_dev *pctldev,
- unsigned pin,
- unsigned long *config)
-{
- return -ENOTSUPP;
-}
-
-
-/* Goes through the configs and update register val/mask */
-static int capri_std_pin_update(struct pinctrl_dev *pctldev,
- unsigned pin,
- unsigned long *configs,
- unsigned num_configs,
- u32 *val,
- u32 *mask)
-{
- struct capri_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
- int i;
- enum pin_config_param param;
- u16 arg;
-
- for (i = 0; i < num_configs; i++) {
- param = pinconf_to_config_param(configs[i]);
- arg = pinconf_to_config_argument(configs[i]);
-
- switch (param) {
- case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
- arg = (arg >= 1 ? 1 : 0);
- capri_pin_update(val, mask, arg,
- CAPRI_PIN_SHIFT(STD, HYST),
- CAPRI_PIN_MASK(STD, HYST));
- break;
- /*
- * The pin bias can only be one of pull-up, pull-down, or
- * disable. The user does not need to specify a value for the
- * property, and the default value from pinconf-generic is
- * ignored.
- */
- case PIN_CONFIG_BIAS_DISABLE:
- capri_pin_update(val, mask, 0,
- CAPRI_PIN_SHIFT(STD, PULL_UP),
- CAPRI_PIN_MASK(STD, PULL_UP));
- capri_pin_update(val, mask, 0,
- CAPRI_PIN_SHIFT(STD, PULL_DN),
- CAPRI_PIN_MASK(STD, PULL_DN));
- break;
-
- case PIN_CONFIG_BIAS_PULL_UP:
- capri_pin_update(val, mask, 1,
- CAPRI_PIN_SHIFT(STD, PULL_UP),
- CAPRI_PIN_MASK(STD, PULL_UP));
- capri_pin_update(val, mask, 0,
- CAPRI_PIN_SHIFT(STD, PULL_DN),
- CAPRI_PIN_MASK(STD, PULL_DN));
- break;
-
- case PIN_CONFIG_BIAS_PULL_DOWN:
- capri_pin_update(val, mask, 0,
- CAPRI_PIN_SHIFT(STD, PULL_UP),
- CAPRI_PIN_MASK(STD, PULL_UP));
- capri_pin_update(val, mask, 1,
- CAPRI_PIN_SHIFT(STD, PULL_DN),
- CAPRI_PIN_MASK(STD, PULL_DN));
- break;
-
- case PIN_CONFIG_SLEW_RATE:
- arg = (arg >= 1 ? 1 : 0);
- capri_pin_update(val, mask, arg,
- CAPRI_PIN_SHIFT(STD, SLEW),
- CAPRI_PIN_MASK(STD, SLEW));
- break;
-
- case PIN_CONFIG_INPUT_ENABLE:
- /* inversed since register is for input _disable_ */
- arg = (arg >= 1 ? 0 : 1);
- capri_pin_update(val, mask, arg,
- CAPRI_PIN_SHIFT(STD, INPUT_DIS),
- CAPRI_PIN_MASK(STD, INPUT_DIS));
- break;
-
- case PIN_CONFIG_DRIVE_STRENGTH:
- /* Valid range is 2-16 mA, even numbers only */
- if ((arg < 2) || (arg > 16) || (arg % 2)) {
- dev_err(pctldev->dev,
- "Invalid Drive Strength value (%d) for "
- "pin %s (%d). Valid values are "
- "(2..16) mA, even numbers only.\n",
- arg, pdata->pins[pin].name, pin);
- return -EINVAL;
- }
- capri_pin_update(val, mask, (arg/2)-1,
- CAPRI_PIN_SHIFT(STD, DRV_STR),
- CAPRI_PIN_MASK(STD, DRV_STR));
- break;
-
- default:
- dev_err(pctldev->dev,
- "Unrecognized pin config %d for pin %s (%d).\n",
- param, pdata->pins[pin].name, pin);
- return -EINVAL;
-
- } /* switch config */
- } /* for each config */
-
- return 0;
-}
-
-/*
- * The pull-up strength for an I2C pin is represented by bits 4-6 in the
- * register with the following mapping:
- * 0b000: No pull-up
- * 0b001: 1200 Ohm
- * 0b010: 1800 Ohm
- * 0b011: 720 Ohm
- * 0b100: 2700 Ohm
- * 0b101: 831 Ohm
- * 0b110: 1080 Ohm
- * 0b111: 568 Ohm
- * This array maps pull-up strength in Ohms to register values (1+index).
- */
-static const u16 capri_pullup_map[] = {1200, 1800, 720, 2700, 831, 1080, 568};
-
-/* Goes through the configs and update register val/mask */
-static int capri_i2c_pin_update(struct pinctrl_dev *pctldev,
- unsigned pin,
- unsigned long *configs,
- unsigned num_configs,
- u32 *val,
- u32 *mask)
-{
- struct capri_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
- int i, j;
- enum pin_config_param param;
- u16 arg;
-
- for (i = 0; i < num_configs; i++) {
- param = pinconf_to_config_param(configs[i]);
- arg = pinconf_to_config_argument(configs[i]);
-
- switch (param) {
- case PIN_CONFIG_BIAS_PULL_UP:
- for (j = 0; j < ARRAY_SIZE(capri_pullup_map); j++)
- if (capri_pullup_map[j] == arg)
- break;
-
- if (j == ARRAY_SIZE(capri_pullup_map)) {
- dev_err(pctldev->dev,
- "Invalid pull-up value (%d) for pin %s "
- "(%d). Valid values are 568, 720, 831, "
- "1080, 1200, 1800, 2700 Ohms.\n",
- arg, pdata->pins[pin].name, pin);
- return -EINVAL;
- }
-
- capri_pin_update(val, mask, j+1,
- CAPRI_PIN_SHIFT(I2C, PULL_UP_STR),
- CAPRI_PIN_MASK(I2C, PULL_UP_STR));
- break;
-
- case PIN_CONFIG_BIAS_DISABLE:
- capri_pin_update(val, mask, 0,
- CAPRI_PIN_SHIFT(I2C, PULL_UP_STR),
- CAPRI_PIN_MASK(I2C, PULL_UP_STR));
- break;
-
- case PIN_CONFIG_SLEW_RATE:
- arg = (arg >= 1 ? 1 : 0);
- capri_pin_update(val, mask, arg,
- CAPRI_PIN_SHIFT(I2C, SLEW),
- CAPRI_PIN_MASK(I2C, SLEW));
- break;
-
- case PIN_CONFIG_INPUT_ENABLE:
- /* inversed since register is for input _disable_ */
- arg = (arg >= 1 ? 0 : 1);
- capri_pin_update(val, mask, arg,
- CAPRI_PIN_SHIFT(I2C, INPUT_DIS),
- CAPRI_PIN_MASK(I2C, INPUT_DIS));
- break;
-
- default:
- dev_err(pctldev->dev,
- "Unrecognized pin config %d for pin %s (%d).\n",
- param, pdata->pins[pin].name, pin);
- return -EINVAL;
-
- } /* switch config */
- } /* for each config */
-
- return 0;
-}
-
-/* Goes through the configs and update register val/mask */
-static int capri_hdmi_pin_update(struct pinctrl_dev *pctldev,
- unsigned pin,
- unsigned long *configs,
- unsigned num_configs,
- u32 *val,
- u32 *mask)
-{
- struct capri_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
- int i;
- enum pin_config_param param;
- u16 arg;
-
- for (i = 0; i < num_configs; i++) {
- param = pinconf_to_config_param(configs[i]);
- arg = pinconf_to_config_argument(configs[i]);
-
- switch (param) {
- case PIN_CONFIG_SLEW_RATE:
- arg = (arg >= 1 ? 1 : 0);
- capri_pin_update(val, mask, arg,
- CAPRI_PIN_SHIFT(HDMI, MODE),
- CAPRI_PIN_MASK(HDMI, MODE));
- break;
-
- case PIN_CONFIG_INPUT_ENABLE:
- /* inversed since register is for input _disable_ */
- arg = (arg >= 1 ? 0 : 1);
- capri_pin_update(val, mask, arg,
- CAPRI_PIN_SHIFT(HDMI, INPUT_DIS),
- CAPRI_PIN_MASK(HDMI, INPUT_DIS));
- break;
-
- default:
- dev_err(pctldev->dev,
- "Unrecognized pin config %d for pin %s (%d).\n",
- param, pdata->pins[pin].name, pin);
- return -EINVAL;
-
- } /* switch config */
- } /* for each config */
-
- return 0;
-}
-
-static int capri_pinctrl_pin_config_set(struct pinctrl_dev *pctldev,
- unsigned pin,
- unsigned long *configs,
- unsigned num_configs)
-{
- struct capri_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
- enum capri_pin_type pin_type;
- u32 offset = 4 * pin;
- u32 cfg_val, cfg_mask;
- int rc;
-
- cfg_val = 0;
- cfg_mask = 0;
- pin_type = pin_type_get(pctldev, pin);
-
- /* Different pins have different configuration options */
- switch (pin_type) {
- case CAPRI_PIN_TYPE_STD:
- rc = capri_std_pin_update(pctldev, pin, configs, num_configs,
- &cfg_val, &cfg_mask);
- break;
-
- case CAPRI_PIN_TYPE_I2C:
- rc = capri_i2c_pin_update(pctldev, pin, configs, num_configs,
- &cfg_val, &cfg_mask);
- break;
-
- case CAPRI_PIN_TYPE_HDMI:
- rc = capri_hdmi_pin_update(pctldev, pin, configs, num_configs,
- &cfg_val, &cfg_mask);
- break;
-
- default:
- dev_err(pctldev->dev, "Unknown pin type for pin %s (%d).\n",
- pdata->pins[pin].name, pin);
- return -EINVAL;
-
- } /* switch pin type */
-
- if (rc)
- return rc;
-
- dev_dbg(pctldev->dev,
- "%s(): Set pin %s (%d) with config 0x%x, mask 0x%x\n",
- __func__, pdata->pins[pin].name, pin, cfg_val, cfg_mask);
-
- rc = regmap_update_bits(pdata->regmap, offset, cfg_mask, cfg_val);
- if (rc) {
- dev_err(pctldev->dev,
- "Error updating register for pin %s (%d).\n",
- pdata->pins[pin].name, pin);
- return rc;
- }
-
- return 0;
-}
-
-static struct pinconf_ops capri_pinctrl_pinconf_ops = {
- .pin_config_get = capri_pinctrl_pin_config_get,
- .pin_config_set = capri_pinctrl_pin_config_set,
-};
-
-static struct pinctrl_desc capri_pinctrl_desc = {
- /* name, pins, npins members initialized in probe function */
- .pctlops = &capri_pinctrl_ops,
- .pmxops = &capri_pinctrl_pinmux_ops,
- .confops = &capri_pinctrl_pinconf_ops,
- .owner = THIS_MODULE,
-};
-
-int __init capri_pinctrl_probe(struct platform_device *pdev)
-{
- struct capri_pinctrl_data *pdata = &capri_pinctrl;
- struct resource *res;
- struct pinctrl_dev *pctl;
-
- /* So far We can assume there is only 1 bank of registers */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&pdev->dev, "Missing MEM resource\n");
- return -ENODEV;
- }
-
- pdata->reg_base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(pdata->reg_base)) {
- dev_err(&pdev->dev, "Failed to ioremap MEM resource\n");
- return -ENODEV;
- }
-
- /* Initialize the dynamic part of pinctrl_desc */
- pdata->regmap = devm_regmap_init_mmio(&pdev->dev, pdata->reg_base,
- &capri_pinctrl_regmap_config);
- if (IS_ERR(pdata->regmap)) {
- dev_err(&pdev->dev, "Regmap MMIO init failed.\n");
- return -ENODEV;
- }
-
- capri_pinctrl_desc.name = dev_name(&pdev->dev);
- capri_pinctrl_desc.pins = capri_pinctrl.pins;
- capri_pinctrl_desc.npins = capri_pinctrl.npins;
-
- pctl = pinctrl_register(&capri_pinctrl_desc,
- &pdev->dev,
- pdata);
- if (!pctl) {
- dev_err(&pdev->dev, "Failed to register pinctrl\n");
- return -ENODEV;
- }
-
- platform_set_drvdata(pdev, pdata);
-
- return 0;
-}
-
-static struct of_device_id capri_pinctrl_of_match[] = {
- { .compatible = "brcm,bcm11351-pinctrl", },
- { },
-};
-
-static struct platform_driver capri_pinctrl_driver = {
- .driver = {
- .name = "bcm-capri-pinctrl",
- .owner = THIS_MODULE,
- .of_match_table = capri_pinctrl_of_match,
- },
-};
-
-module_platform_driver_probe(capri_pinctrl_driver, capri_pinctrl_probe);
-
-MODULE_AUTHOR("Sherman Yin <syin@broadcom.com>");
-MODULE_DESCRIPTION("Broadcom Capri pinctrl driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-msm.c b/drivers/pinctrl/pinctrl-msm.c
index 38d579b47f31..e43fbce56598 100644
--- a/drivers/pinctrl/pinctrl-msm.c
+++ b/drivers/pinctrl/pinctrl-msm.c
@@ -665,7 +665,10 @@ static void msm_gpio_irq_ack(struct irq_data *d)
spin_lock_irqsave(&pctrl->lock, flags);
val = readl(pctrl->regs + g->intr_status_reg);
- val &= ~BIT(g->intr_status_bit);
+ if (g->intr_ack_high)
+ val |= BIT(g->intr_status_bit);
+ else
+ val &= ~BIT(g->intr_status_bit);
writel(val, pctrl->regs + g->intr_status_reg);
if (test_bit(d->hwirq, pctrl->dual_edge_irqs))
@@ -744,6 +747,7 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
break;
case IRQ_TYPE_EDGE_BOTH:
val |= BIT(g->intr_detection_bit);
+ val |= BIT(g->intr_polarity_bit);
break;
case IRQ_TYPE_LEVEL_LOW:
break;
diff --git a/drivers/pinctrl/pinctrl-msm.h b/drivers/pinctrl/pinctrl-msm.h
index 8fbe9fb19f36..6e26f1b676d7 100644
--- a/drivers/pinctrl/pinctrl-msm.h
+++ b/drivers/pinctrl/pinctrl-msm.h
@@ -84,6 +84,7 @@ struct msm_pingroup {
unsigned intr_enable_bit:5;
unsigned intr_status_bit:5;
+ unsigned intr_ack_high:1;
unsigned intr_target_bit:5;
unsigned intr_raw_status_bit:5;
diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c
index 208341fd57d2..8f6f16ef73f3 100644
--- a/drivers/pinctrl/pinctrl-nomadik.c
+++ b/drivers/pinctrl/pinctrl-nomadik.c
@@ -877,7 +877,6 @@ static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip);
u32 status;
- pr_err("PLONK IRQ %d\n", irq);
clk_enable(nmk_chip->clk);
status = readl(nmk_chip->addr + NMK_GPIO_IS);
clk_disable(nmk_chip->clk);
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index 46dddc159286..96c60d230c13 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -342,7 +342,7 @@ static const struct pinctrl_ops rockchip_pctrl_ops = {
* @pin: pin to change
* @mux: new mux function to set
*/
-static void rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
+static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
{
struct rockchip_pinctrl *info = bank->drvdata;
void __iomem *reg = info->reg_base + info->ctrl->mux_offset;
@@ -350,6 +350,20 @@ static void rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
u8 bit;
u32 data;
+ /*
+ * The first 16 pins of rk3188_bank0 are always gpios and do not have
+ * a mux register at all.
+ */
+ if (bank->bank_type == RK3188_BANK0 && pin < 16) {
+ if (mux != RK_FUNC_GPIO) {
+ dev_err(info->dev,
+ "pin %d only supports a gpio mux\n", pin);
+ return -ENOTSUPP;
+ } else {
+ return 0;
+ }
+ }
+
dev_dbg(info->dev, "setting mux of GPIO%d-%d to %d\n",
bank->bank_num, pin, mux);
@@ -365,6 +379,8 @@ static void rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
writel(data, reg);
spin_unlock_irqrestore(&bank->slock, flags);
+
+ return 0;
}
#define RK2928_PULL_OFFSET 0x118
@@ -560,7 +576,7 @@ static int rockchip_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector,
const unsigned int *pins = info->groups[group].pins;
const struct rockchip_pin_config *data = info->groups[group].data;
struct rockchip_pin_bank *bank;
- int cnt;
+ int cnt, ret = 0;
dev_dbg(info->dev, "enable function %s group %s\n",
info->functions[selector].name, info->groups[group].name);
@@ -571,8 +587,18 @@ static int rockchip_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector,
*/
for (cnt = 0; cnt < info->groups[group].npins; cnt++) {
bank = pin_to_bank(info, pins[cnt]);
- rockchip_set_mux(bank, pins[cnt] - bank->pin_base,
- data[cnt].func);
+ ret = rockchip_set_mux(bank, pins[cnt] - bank->pin_base,
+ data[cnt].func);
+ if (ret)
+ break;
+ }
+
+ if (ret) {
+ /* revert the already done pin settings */
+ for (cnt--; cnt >= 0; cnt--)
+ rockchip_set_mux(bank, pins[cnt] - bank->pin_base, 0);
+
+ return ret;
}
return 0;
@@ -607,7 +633,7 @@ static int rockchip_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
struct rockchip_pin_bank *bank;
struct gpio_chip *chip;
- int pin;
+ int pin, ret;
u32 data;
chip = range->gc;
@@ -617,7 +643,9 @@ static int rockchip_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
dev_dbg(info->dev, "gpio_direction for pin %u as %s-%d to %s\n",
offset, range->name, pin, input ? "input" : "output");
- rockchip_set_mux(bank, pin, RK_FUNC_GPIO);
+ ret = rockchip_set_mux(bank, pin, RK_FUNC_GPIO);
+ if (ret < 0)
+ return ret;
data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR);
/* set bit to 1 for output, 0 for input */
@@ -1144,9 +1172,13 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
u32 polarity;
u32 level;
u32 data;
+ int ret;
/* make sure the pin is configured as gpio input */
- rockchip_set_mux(bank, d->hwirq, RK_FUNC_GPIO);
+ ret = rockchip_set_mux(bank, d->hwirq, RK_FUNC_GPIO);
+ if (ret < 0)
+ return ret;
+
data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR);
data &= ~mask;
writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR);
@@ -1534,7 +1566,7 @@ static struct rockchip_pin_ctrl rk3188_pin_ctrl = {
.nr_banks = ARRAY_SIZE(rk3188_pin_banks),
.label = "RK3188-GPIO",
.type = RK3188,
- .mux_offset = 0x68,
+ .mux_offset = 0x60,
.pull_calc_reg = rk3188_calc_pull_reg_and_bit,
};
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 81075f2a1d3f..2960557bfed9 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -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",
diff --git a/drivers/pinctrl/pinctrl-tb10x.c b/drivers/pinctrl/pinctrl-tb10x.c
index c5e0f6973a3b..26ca6855f478 100644
--- a/drivers/pinctrl/pinctrl-tb10x.c
+++ b/drivers/pinctrl/pinctrl-tb10x.c
@@ -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
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c
index 48093719167a..f5cd3f961808 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c
@@ -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,
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
index 5186d70c49d4..7868bf3a0f91 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
@@ -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] */
diff --git a/drivers/pinctrl/vt8500/pinctrl-wmt.c b/drivers/pinctrl/vt8500/pinctrl-wmt.c
index 9802b67040cc..2c61281bebd7 100644
--- a/drivers/pinctrl/vt8500/pinctrl-wmt.c
+++ b/drivers/pinctrl/vt8500/pinctrl-wmt.c
@@ -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,
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index 9f611cbbc294..c31aa07b3ba5 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -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
diff --git a/drivers/pnp/pnpbios/bioscalls.c b/drivers/pnp/pnpbios/bioscalls.c
index deb7f4bcdb7b..438d4c72c7b3 100644
--- a/drivers/pnp/pnpbios/bioscalls.c
+++ b/drivers/pnp/pnpbios/bioscalls.c
@@ -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"
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c
index 258fef272ea7..ebf0d6710b5a 100644
--- a/drivers/pnp/quirks.c
+++ b/drivers/pnp/quirks.c
@@ -15,6 +15,7 @@
#include <linux/types.h>
#include <linux/kernel.h>
+#include <linux/pci.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/pnp.h>
@@ -334,6 +335,81 @@ static void quirk_amd_mmconfig_area(struct pnp_dev *dev)
}
#endif
+#ifdef CONFIG_PCI
+/* Device IDs of parts that have 32KB MCH space */
+static const unsigned int mch_quirk_devices[] = {
+ 0x0154, /* Ivy Bridge */
+ 0x0c00, /* Haswell */
+};
+
+static struct pci_dev *get_intel_host(void)
+{
+ int i;
+ struct pci_dev *host;
+
+ for (i = 0; i < ARRAY_SIZE(mch_quirk_devices); i++) {
+ host = pci_get_device(PCI_VENDOR_ID_INTEL, mch_quirk_devices[i],
+ NULL);
+ if (host)
+ return host;
+ }
+ return NULL;
+}
+
+static void quirk_intel_mch(struct pnp_dev *dev)
+{
+ struct pci_dev *host;
+ u32 addr_lo, addr_hi;
+ struct pci_bus_region region;
+ struct resource mch;
+ struct pnp_resource *pnp_res;
+ struct resource *res;
+
+ host = get_intel_host();
+ if (!host)
+ return;
+
+ /*
+ * MCHBAR is not an architected PCI BAR, so MCH space is usually
+ * reported as a PNP0C02 resource. The MCH space was originally
+ * 16KB, but is 32KB in newer parts. Some BIOSes still report a
+ * PNP0C02 resource that is only 16KB, which means the rest of the
+ * MCH space is consumed but unreported.
+ */
+
+ /*
+ * Read MCHBAR for Host Member Mapped Register Range Base
+ * https://www-ssl.intel.com/content/www/us/en/processors/core/4th-gen-core-family-desktop-vol-2-datasheet
+ * Sec 3.1.12.
+ */
+ pci_read_config_dword(host, 0x48, &addr_lo);
+ region.start = addr_lo & ~0x7fff;
+ pci_read_config_dword(host, 0x4c, &addr_hi);
+ region.start |= (u64) addr_hi << 32;
+ region.end = region.start + 32*1024 - 1;
+
+ memset(&mch, 0, sizeof(mch));
+ mch.flags = IORESOURCE_MEM;
+ pcibios_bus_to_resource(host->bus, &mch, &region);
+
+ list_for_each_entry(pnp_res, &dev->resources, list) {
+ res = &pnp_res->res;
+ if (res->end < mch.start || res->start > mch.end)
+ continue; /* no overlap */
+ if (res->start == mch.start && res->end == mch.end)
+ continue; /* exact match */
+
+ dev_info(&dev->dev, FW_BUG "PNP resource %pR covers only part of %s Intel MCH; extending to %pR\n",
+ res, pci_name(host), &mch);
+ res->start = mch.start;
+ res->end = mch.end;
+ break;
+ }
+
+ pci_dev_put(host);
+}
+#endif
+
/*
* PnP Quirks
* Cards or devices that need some tweaking due to incomplete resource info
@@ -364,6 +440,9 @@ static struct pnp_fixup pnp_fixups[] = {
#ifdef CONFIG_AMD_NB
{"PNP0c01", quirk_amd_mmconfig_area},
#endif
+#ifdef CONFIG_PCI
+ {"PNP0c02", quirk_intel_mch},
+#endif
{""}
};
diff --git a/drivers/power/reset/vexpress-poweroff.c b/drivers/power/reset/vexpress-poweroff.c
index 476aa495c110..b95cf71ed695 100644
--- a/drivers/power/reset/vexpress-poweroff.c
+++ b/drivers/power/reset/vexpress-poweroff.c
@@ -11,7 +11,7 @@
* Copyright (C) 2012 ARM Limited
*/
-#include <linux/jiffies.h>
+#include <linux/delay.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
@@ -23,17 +23,12 @@
static void vexpress_reset_do(struct device *dev, const char *what)
{
int err = -ENOENT;
- struct vexpress_config_func *func =
- vexpress_config_func_get_by_dev(dev);
+ struct vexpress_config_func *func = dev_get_drvdata(dev);
if (func) {
- unsigned long timeout;
-
err = vexpress_config_write(func, 0, 0);
-
- timeout = jiffies + HZ;
- while (time_before(jiffies, timeout))
- cpu_relax();
+ if (!err)
+ mdelay(1000);
}
dev_emerg(dev, "Unable to %s (%d)\n", what, err);
@@ -96,12 +91,18 @@ static int vexpress_reset_probe(struct platform_device *pdev)
enum vexpress_reset_func func;
const struct of_device_id *match =
of_match_device(vexpress_reset_of_match, &pdev->dev);
+ struct vexpress_config_func *config_func;
if (match)
func = (enum vexpress_reset_func)match->data;
else
func = pdev->id_entry->driver_data;
+ config_func = vexpress_config_func_get_by_dev(&pdev->dev);
+ if (!config_func)
+ return -EINVAL;
+ dev_set_drvdata(&pdev->dev, config_func);
+
switch (func) {
case FUNC_SHUTDOWN:
vexpress_power_off_device = &pdev->dev;
diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
index 6963bdf54175..6aea373547f6 100644
--- a/drivers/ptp/Kconfig
+++ b/drivers/ptp/Kconfig
@@ -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
diff --git a/drivers/pwm/pwm-spear.c b/drivers/pwm/pwm-spear.c
index 8ad26b8bf418..cb2d4f0f9711 100644
--- a/drivers/pwm/pwm-spear.c
+++ b/drivers/pwm/pwm-spear.c
@@ -2,7 +2,7 @@
* ST Microelectronics SPEAr Pulse Width Modulator driver
*
* Copyright (C) 2012 ST Microelectronics
- * Shiraz Hashim <shiraz.hashim@st.com>
+ * Shiraz Hashim <shiraz.linux.kernel@gmail.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
@@ -264,6 +264,6 @@ static struct platform_driver spear_pwm_driver = {
module_platform_driver(spear_pwm_driver);
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Shiraz Hashim <shiraz.hashim@st.com>");
+MODULE_AUTHOR("Shiraz Hashim <shiraz.linux.kernel@gmail.com>");
MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.com>");
MODULE_ALIAS("platform:spear-pwm");
diff --git a/drivers/regulator/pbias-regulator.c b/drivers/regulator/pbias-regulator.c
index ded3b3574209..6d38be3d970c 100644
--- a/drivers/regulator/pbias-regulator.c
+++ b/drivers/regulator/pbias-regulator.c
@@ -38,66 +38,24 @@ struct pbias_reg_info {
struct pbias_regulator_data {
struct regulator_desc desc;
void __iomem *pbias_addr;
- unsigned int pbias_reg;
struct regulator_dev *dev;
struct regmap *syscon;
const struct pbias_reg_info *info;
int voltage;
};
-static int pbias_regulator_set_voltage(struct regulator_dev *dev,
- int min_uV, int max_uV, unsigned *selector)
-{
- struct pbias_regulator_data *data = rdev_get_drvdata(dev);
- const struct pbias_reg_info *info = data->info;
- int ret, vmode;
-
- if (min_uV <= 1800000)
- vmode = 0;
- else if (min_uV > 1800000)
- vmode = info->vmode;
-
- ret = regmap_update_bits(data->syscon, data->pbias_reg,
- info->vmode, vmode);
-
- return ret;
-}
-
-static int pbias_regulator_get_voltage(struct regulator_dev *rdev)
-{
- struct pbias_regulator_data *data = rdev_get_drvdata(rdev);
- const struct pbias_reg_info *info = data->info;
- int value, voltage;
-
- regmap_read(data->syscon, data->pbias_reg, &value);
- value &= info->vmode;
-
- voltage = value ? 3000000 : 1800000;
-
- return voltage;
-}
+static const unsigned int pbias_volt_table[] = {
+ 1800000,
+ 3000000
+};
static int pbias_regulator_enable(struct regulator_dev *rdev)
{
struct pbias_regulator_data *data = rdev_get_drvdata(rdev);
const struct pbias_reg_info *info = data->info;
- int ret;
-
- ret = regmap_update_bits(data->syscon, data->pbias_reg,
- info->enable_mask, info->enable);
-
- return ret;
-}
-
-static int pbias_regulator_disable(struct regulator_dev *rdev)
-{
- struct pbias_regulator_data *data = rdev_get_drvdata(rdev);
- const struct pbias_reg_info *info = data->info;
- int ret;
- ret = regmap_update_bits(data->syscon, data->pbias_reg,
- info->enable_mask, 0);
- return ret;
+ return regmap_update_bits(data->syscon, rdev->desc->enable_reg,
+ info->enable_mask, info->enable);
}
static int pbias_regulator_is_enable(struct regulator_dev *rdev)
@@ -106,17 +64,18 @@ static int pbias_regulator_is_enable(struct regulator_dev *rdev)
const struct pbias_reg_info *info = data->info;
int value;
- regmap_read(data->syscon, data->pbias_reg, &value);
+ regmap_read(data->syscon, rdev->desc->enable_reg, &value);
- return (value & info->enable_mask) == info->enable_mask;
+ return (value & info->enable_mask) == info->enable;
}
static struct regulator_ops pbias_regulator_voltage_ops = {
- .set_voltage = pbias_regulator_set_voltage,
- .get_voltage = pbias_regulator_get_voltage,
- .enable = pbias_regulator_enable,
- .disable = pbias_regulator_disable,
- .is_enabled = pbias_regulator_is_enable,
+ .list_voltage = regulator_list_voltage_table,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .enable = pbias_regulator_enable,
+ .disable = regulator_disable_regmap,
+ .is_enabled = pbias_regulator_is_enable,
};
static const struct pbias_reg_info pbias_mmc_omap2430 = {
@@ -192,6 +151,7 @@ static int pbias_regulator_probe(struct platform_device *pdev)
if (IS_ERR(syscon))
return PTR_ERR(syscon);
+ cfg.regmap = syscon;
cfg.dev = &pdev->dev;
for (idx = 0; idx < PBIAS_NUM_REGS && data_idx < count; idx++) {
@@ -207,15 +167,19 @@ static int pbias_regulator_probe(struct platform_device *pdev)
if (!res)
return -EINVAL;
- drvdata[data_idx].pbias_reg = res->start;
drvdata[data_idx].syscon = syscon;
drvdata[data_idx].info = info;
drvdata[data_idx].desc.name = info->name;
drvdata[data_idx].desc.owner = THIS_MODULE;
drvdata[data_idx].desc.type = REGULATOR_VOLTAGE;
drvdata[data_idx].desc.ops = &pbias_regulator_voltage_ops;
+ drvdata[data_idx].desc.volt_table = pbias_volt_table;
drvdata[data_idx].desc.n_voltages = 2;
drvdata[data_idx].desc.enable_time = info->enable_time;
+ drvdata[data_idx].desc.vsel_reg = res->start;
+ drvdata[data_idx].desc.vsel_mask = info->vmode;
+ drvdata[data_idx].desc.enable_reg = res->start;
+ drvdata[data_idx].desc.enable_mask = info->enable_mask;
cfg.init_data = pbias_matches[idx].init_data;
cfg.driver_data = &drvdata[data_idx];
diff --git a/drivers/rtc/rtc-hym8563.c b/drivers/rtc/rtc-hym8563.c
index bd628a6f981d..e5f13c4310fe 100644
--- a/drivers/rtc/rtc-hym8563.c
+++ b/drivers/rtc/rtc-hym8563.c
@@ -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
diff --git a/drivers/rtc/rtc-pcf8523.c b/drivers/rtc/rtc-pcf8523.c
index 5c8f8226c848..4cdb64be061b 100644
--- a/drivers/rtc/rtc-pcf8523.c
+++ b/drivers/rtc/rtc-pcf8523.c
@@ -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;
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
index 1990285296c6..c316051d9bda 100644
--- a/drivers/s390/char/sclp.c
+++ b/drivers/s390/char/sclp.c
@@ -1252,7 +1252,7 @@ static __init int sclp_initcall(void)
return rc;
sclp_pdev = platform_device_register_simple("sclp", -1, NULL, 0);
- rc = PTR_RET(sclp_pdev);
+ rc = PTR_ERR_OR_ZERO(sclp_pdev);
if (rc)
goto fail_platform_driver_unregister;
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c
index 6e8f90f84e49..6e14999f9e8f 100644
--- a/drivers/s390/char/sclp_cmd.c
+++ b/drivers/s390/char/sclp_cmd.c
@@ -515,7 +515,7 @@ static int __init sclp_detect_standby_memory(void)
if (rc)
goto out;
sclp_pdev = platform_device_register_simple("sclp_mem", -1, NULL, 0);
- rc = PTR_RET(sclp_pdev);
+ rc = PTR_ERR_OR_ZERO(sclp_pdev);
if (rc)
goto out_driver;
sclp_add_standby_memory();
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index 4eed38cd0af6..cd9c91909596 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -97,13 +97,16 @@ static void sclp_vt220_pm_event_fn(struct sclp_register *reg,
static int __sclp_vt220_emit(struct sclp_vt220_request *request);
static void sclp_vt220_emit_current(void);
-/* Registration structure for our interest in SCLP event buffers */
+/* Registration structure for SCLP output event buffers */
static struct sclp_register sclp_vt220_register = {
.send_mask = EVTYP_VT220MSG_MASK,
+ .pm_event_fn = sclp_vt220_pm_event_fn,
+};
+
+/* Registration structure for SCLP input event buffers */
+static struct sclp_register sclp_vt220_register_input = {
.receive_mask = EVTYP_VT220MSG_MASK,
- .state_change_fn = NULL,
.receiver_fn = sclp_vt220_receiver_fn,
- .pm_event_fn = sclp_vt220_pm_event_fn,
};
@@ -715,9 +718,14 @@ static int __init sclp_vt220_tty_init(void)
rc = tty_register_driver(driver);
if (rc)
goto out_init;
+ rc = sclp_register(&sclp_vt220_register_input);
+ if (rc)
+ goto out_reg;
sclp_vt220_driver = driver;
return 0;
+out_reg:
+ tty_unregister_driver(driver);
out_init:
__sclp_vt220_cleanup();
out_driver:
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 9f0ea6cb6922..e3bf885f4a6c 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -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;
+ }
}
/*
diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c
index 296c936cc03c..a8d721ff19eb 100644
--- a/drivers/scsi/atari_scsi.c
+++ b/drivers/scsi/atari_scsi.c
@@ -639,7 +639,7 @@ static int __init atari_scsi_detect(struct scsi_host_template *host)
"double buffer\n");
return 0;
}
- atari_dma_phys_buffer = virt_to_phys(atari_dma_buffer);
+ atari_dma_phys_buffer = atari_stram_to_phys(atari_dma_buffer);
atari_dma_orig_addr = 0;
}
#endif
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 8cf4a0c69baf..9a6e4a2cd072 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -7463,6 +7463,10 @@ static void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h)
if (hpsa_simple_mode)
return;
+ trans_support = readl(&(h->cfgtable->TransportSupport));
+ if (!(trans_support & PERFORMANT_MODE))
+ return;
+
/* Check for I/O accelerator mode support */
if (trans_support & CFGTBL_Trans_io_accel1) {
transMethod |= CFGTBL_Trans_io_accel1 |
@@ -7479,10 +7483,6 @@ static void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h)
}
/* TODO, check that this next line h->nreply_queues is correct */
- trans_support = readl(&(h->cfgtable->TransportSupport));
- if (!(trans_support & PERFORMANT_MODE))
- return;
-
h->nreply_queues = h->msix_vector > 0 ? h->msix_vector : 1;
hpsa_get_max_perf_mode_cmds(h);
/* Performant mode ring buffer and supporting data structures */
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index 7f0af4fcc001..6fd7d40b2c4d 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -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;
}
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 771c16bfdbac..f17aa7aa7879 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -189,6 +189,7 @@ scsi_abort_command(struct scsi_cmnd *scmd)
/*
* Retry after abort failed, escalate to next level.
*/
+ scmd->eh_eflags &= ~SCSI_EH_ABORT_SCHEDULED;
SCSI_LOG_ERROR_RECOVERY(3,
scmd_printk(KERN_INFO, scmd,
"scmd %p previous abort failed\n", scmd));
@@ -920,10 +921,12 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
ses->prot_op = scmd->prot_op;
scmd->prot_op = SCSI_PROT_NORMAL;
+ scmd->eh_eflags = 0;
scmd->cmnd = ses->eh_cmnd;
memset(scmd->cmnd, 0, BLK_MAX_CDB);
memset(&scmd->sdb, 0, sizeof(scmd->sdb));
scmd->request->next_rq = NULL;
+ scmd->result = 0;
if (sense_bytes) {
scmd->sdb.length = min_t(unsigned, SCSI_SENSE_BUFFERSIZE,
@@ -1157,6 +1160,15 @@ int scsi_eh_get_sense(struct list_head *work_q,
__func__));
break;
}
+ if (status_byte(scmd->result) != CHECK_CONDITION)
+ /*
+ * don't request sense if there's no check condition
+ * status because the error we're processing isn't one
+ * that has a sense code (and some devices get
+ * confused by sense requests out of the blue)
+ */
+ continue;
+
SCSI_LOG_ERROR_RECOVERY(2, scmd_printk(KERN_INFO, scmd,
"%s: requesting sense\n",
current->comm));
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 3cc82d3dec78..a0c95cac91f0 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -137,6 +137,7 @@ static void __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, int unbusy)
* lock such that the kblockd_schedule_work() call happens
* before blk_cleanup_queue() finishes.
*/
+ cmd->result = 0;
spin_lock_irqsave(q->queue_lock, flags);
blk_requeue_request(q, cmd->request);
kblockd_schedule_work(&device->requeue_work);
@@ -1042,6 +1043,7 @@ static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb,
*/
int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask)
{
+ struct scsi_device *sdev = cmd->device;
struct request *rq = cmd->request;
int error = scsi_init_sgtable(rq, &cmd->sdb, gfp_mask);
@@ -1089,7 +1091,7 @@ err_exit:
scsi_release_buffers(cmd);
cmd->request->special = NULL;
scsi_put_command(cmd);
- put_device(&cmd->device->sdev_gendev);
+ put_device(&sdev->sdev_gendev);
return error;
}
EXPORT_SYMBOL(scsi_init_io);
@@ -1270,7 +1272,7 @@ int scsi_prep_return(struct request_queue *q, struct request *req, int ret)
struct scsi_cmnd *cmd = req->special;
scsi_release_buffers(cmd);
scsi_put_command(cmd);
- put_device(&cmd->device->sdev_gendev);
+ put_device(&sdev->sdev_gendev);
req->special = NULL;
}
break;
diff --git a/drivers/scsi/scsi_netlink.c b/drivers/scsi/scsi_netlink.c
index fe30ea94ffe6..109802f776ed 100644
--- a/drivers/scsi/scsi_netlink.c
+++ b/drivers/scsi/scsi_netlink.c
@@ -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;
}
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index 1b681427dde0..c341f855fadc 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -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);
}
diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
index 16bfd50cd3fe..db3b494e5926 100644
--- a/drivers/scsi/virtio_scsi.c
+++ b/drivers/scsi/virtio_scsi.c
@@ -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;
}
diff --git a/drivers/sh/Makefile b/drivers/sh/Makefile
index fc67f564f02c..788ed9b59b4e 100644
--- a/drivers/sh/Makefile
+++ b/drivers/sh/Makefile
@@ -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
diff --git a/drivers/sh/pm_runtime.c b/drivers/sh/pm_runtime.c
index 8afa5a4589f2..10c65eb51f85 100644
--- a/drivers/sh/pm_runtime.c
+++ b/drivers/sh/pm_runtime.c
@@ -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);
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index 8005f9869481..079e6b1b0cdb 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -1115,8 +1115,11 @@ static int atmel_spi_one_transfer(struct spi_master *master,
atmel_spi_next_xfer_pio(master, xfer);
}
+ /* interrupts are disabled, so free the lock for schedule */
+ atmel_spi_unlock(as);
ret = wait_for_completion_timeout(&as->xfer_completion,
SPI_DMA_TIMEOUT);
+ atmel_spi_lock(as);
if (WARN_ON(ret == 0)) {
dev_err(&spi->dev,
"spi trasfer timeout, err %d\n", ret);
diff --git a/drivers/spi/spi-bfin5xx.c b/drivers/spi/spi-bfin5xx.c
index 55e57c3eb9bd..ebf720b88a2a 100644
--- a/drivers/spi/spi-bfin5xx.c
+++ b/drivers/spi/spi-bfin5xx.c
@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/device.h>
+#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/ioport.h>
diff --git a/drivers/spi/spi-pxa2xx-dma.c b/drivers/spi/spi-pxa2xx-dma.c
index 713af4806f26..f6759dc0153b 100644
--- a/drivers/spi/spi-pxa2xx-dma.c
+++ b/drivers/spi/spi-pxa2xx-dma.c
@@ -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);
diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c
index b032e8885e24..78c66e3c53ed 100644
--- a/drivers/spi/spi-qup.c
+++ b/drivers/spi/spi-qup.c
@@ -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);
diff --git a/drivers/spi/spi-sh-hspi.c b/drivers/spi/spi-sh-hspi.c
index 9009456bdf4d..c8e795ef2e13 100644
--- a/drivers/spi/spi-sh-hspi.c
+++ b/drivers/spi/spi-sh-hspi.c
@@ -244,9 +244,9 @@ static int hspi_probe(struct platform_device *pdev)
return -ENOMEM;
}
- clk = clk_get(NULL, "shyway_clk");
+ clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(clk)) {
- dev_err(&pdev->dev, "shyway_clk is required\n");
+ dev_err(&pdev->dev, "couldn't get clock\n");
ret = -EINVAL;
goto error0;
}
diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c
index 1a77ad52812f..67d8909dcf39 100644
--- a/drivers/spi/spi-sirf.c
+++ b/drivers/spi/spi-sirf.c
@@ -287,8 +287,8 @@ static irqreturn_t spi_sirfsoc_irq(int irq, void *dev_id)
sspi->left_rx_word)
sspi->rx_word(sspi);
- if (spi_stat & (SIRFSOC_SPI_FIFO_EMPTY
- | SIRFSOC_SPI_TXFIFO_THD_REACH))
+ if (spi_stat & (SIRFSOC_SPI_TXFIFO_EMPTY |
+ SIRFSOC_SPI_TXFIFO_THD_REACH))
while (!((readl(sspi->base + SIRFSOC_SPI_TXFIFO_STATUS)
& SIRFSOC_SPI_FIFO_FULL)) &&
sspi->left_tx_word)
@@ -470,7 +470,16 @@ static void spi_sirfsoc_chipselect(struct spi_device *spi, int value)
writel(regval, sspi->base + SIRFSOC_SPI_CTRL);
} else {
int gpio = sspi->chipselect[spi->chip_select];
- gpio_direction_output(gpio, spi->mode & SPI_CS_HIGH ? 0 : 1);
+ switch (value) {
+ case BITBANG_CS_ACTIVE:
+ gpio_direction_output(gpio,
+ spi->mode & SPI_CS_HIGH ? 1 : 0);
+ break;
+ case BITBANG_CS_INACTIVE:
+ gpio_direction_output(gpio,
+ spi->mode & SPI_CS_HIGH ? 0 : 1);
+ break;
+ }
}
}
@@ -559,6 +568,11 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
regval &= ~SIRFSOC_SPI_CMD_MODE;
sspi->tx_by_cmd = false;
}
+ /*
+ * set spi controller in RISC chipselect mode, we are controlling CS by
+ * software BITBANG_CS_ACTIVE and BITBANG_CS_INACTIVE.
+ */
+ regval |= SIRFSOC_SPI_CS_IO_MODE;
writel(regval, sspi->base + SIRFSOC_SPI_CTRL);
if (IS_DMA_VALID(t)) {
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 4eb9bf02996c..939edf473235 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -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);
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index ea5efb426f75..22365f140bec 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -40,8 +40,6 @@ source "drivers/staging/olpc_dcon/Kconfig"
source "drivers/staging/panel/Kconfig"
-source "drivers/staging/rtl8187se/Kconfig"
-
source "drivers/staging/rtl8192u/Kconfig"
source "drivers/staging/rtl8192e/Kconfig"
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 86e020c2ad0d..fbe84ed2d048 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -12,7 +12,6 @@ obj-$(CONFIG_PRISM2_USB) += wlan-ng/
obj-$(CONFIG_COMEDI) += comedi/
obj-$(CONFIG_FB_OLPC_DCON) += olpc_dcon/
obj-$(CONFIG_PANEL) += panel/
-obj-$(CONFIG_R8187SE) += rtl8187se/
obj-$(CONFIG_RTL8192U) += rtl8192u/
obj-$(CONFIG_RTL8192E) += rtl8192e/
obj-$(CONFIG_R8712U) += rtl8712/
diff --git a/drivers/staging/comedi/comedi_buf.c b/drivers/staging/comedi/comedi_buf.c
index 924fce977985..257595016161 100644
--- a/drivers/staging/comedi/comedi_buf.c
+++ b/drivers/staging/comedi/comedi_buf.c
@@ -61,6 +61,8 @@ static void __comedi_buf_free(struct comedi_device *dev,
struct comedi_subdevice *s)
{
struct comedi_async *async = s->async;
+ struct comedi_buf_map *bm;
+ unsigned long flags;
if (async->prealloc_buf) {
vunmap(async->prealloc_buf);
@@ -68,8 +70,11 @@ static void __comedi_buf_free(struct comedi_device *dev,
async->prealloc_bufsz = 0;
}
- comedi_buf_map_put(async->buf_map);
+ spin_lock_irqsave(&s->spin_lock, flags);
+ bm = async->buf_map;
async->buf_map = NULL;
+ spin_unlock_irqrestore(&s->spin_lock, flags);
+ comedi_buf_map_put(bm);
}
static void __comedi_buf_alloc(struct comedi_device *dev,
@@ -80,6 +85,7 @@ static void __comedi_buf_alloc(struct comedi_device *dev,
struct page **pages = NULL;
struct comedi_buf_map *bm;
struct comedi_buf_page *buf;
+ unsigned long flags;
unsigned i;
if (!IS_ENABLED(CONFIG_HAS_DMA) && s->async_dma_dir != DMA_NONE) {
@@ -92,8 +98,10 @@ static void __comedi_buf_alloc(struct comedi_device *dev,
if (!bm)
return;
- async->buf_map = bm;
kref_init(&bm->refcount);
+ spin_lock_irqsave(&s->spin_lock, flags);
+ async->buf_map = bm;
+ spin_unlock_irqrestore(&s->spin_lock, flags);
bm->dma_dir = s->async_dma_dir;
if (bm->dma_dir != DMA_NONE)
/* Need ref to hardware device to free buffer later. */
@@ -127,7 +135,9 @@ static void __comedi_buf_alloc(struct comedi_device *dev,
pages[i] = virt_to_page(buf->virt_addr);
}
+ spin_lock_irqsave(&s->spin_lock, flags);
bm->n_pages = i;
+ spin_unlock_irqrestore(&s->spin_lock, flags);
/* vmap the prealloc_buf if all the pages were allocated */
if (i == n_pages)
@@ -150,6 +160,29 @@ int comedi_buf_map_put(struct comedi_buf_map *bm)
return 1;
}
+/* returns s->async->buf_map and increments its kref refcount */
+struct comedi_buf_map *
+comedi_buf_map_from_subdev_get(struct comedi_subdevice *s)
+{
+ struct comedi_async *async = s->async;
+ struct comedi_buf_map *bm = NULL;
+ unsigned long flags;
+
+ if (!async)
+ return NULL;
+
+ spin_lock_irqsave(&s->spin_lock, flags);
+ bm = async->buf_map;
+ /* only want it if buffer pages allocated */
+ if (bm && bm->n_pages)
+ comedi_buf_map_get(bm);
+ else
+ bm = NULL;
+ spin_unlock_irqrestore(&s->spin_lock, flags);
+
+ return bm;
+}
+
bool comedi_buf_is_mmapped(struct comedi_async *async)
{
struct comedi_buf_map *bm = async->buf_map;
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index ea6dc36d753b..acc80197e35e 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -1926,14 +1926,21 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
struct comedi_device *dev = file->private_data;
struct comedi_subdevice *s;
struct comedi_async *async;
- struct comedi_buf_map *bm;
+ struct comedi_buf_map *bm = NULL;
unsigned long start = vma->vm_start;
unsigned long size;
int n_pages;
int i;
int retval;
- mutex_lock(&dev->mutex);
+ /*
+ * 'trylock' avoids circular dependency with current->mm->mmap_sem
+ * and down-reading &dev->attach_lock should normally succeed without
+ * contention unless the device is in the process of being attached
+ * or detached.
+ */
+ if (!down_read_trylock(&dev->attach_lock))
+ return -EAGAIN;
if (!dev->attached) {
dev_dbg(dev->class_dev, "no driver attached\n");
@@ -1973,7 +1980,9 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
}
n_pages = size >> PAGE_SHIFT;
- bm = async->buf_map;
+
+ /* get reference to current buf map (if any) */
+ bm = comedi_buf_map_from_subdev_get(s);
if (!bm || n_pages > bm->n_pages) {
retval = -EINVAL;
goto done;
@@ -1997,7 +2006,8 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
retval = 0;
done:
- mutex_unlock(&dev->mutex);
+ up_read(&dev->attach_lock);
+ comedi_buf_map_put(bm); /* put reference to buf map - okay if NULL */
return retval;
}
diff --git a/drivers/staging/comedi/comedi_internal.h b/drivers/staging/comedi/comedi_internal.h
index 9a746570f161..a492f2d2436e 100644
--- a/drivers/staging/comedi/comedi_internal.h
+++ b/drivers/staging/comedi/comedi_internal.h
@@ -19,6 +19,8 @@ void comedi_buf_reset(struct comedi_async *async);
bool comedi_buf_is_mmapped(struct comedi_async *async);
void comedi_buf_map_get(struct comedi_buf_map *bm);
int comedi_buf_map_put(struct comedi_buf_map *bm);
+struct comedi_buf_map *comedi_buf_map_from_subdev_get(
+ struct comedi_subdevice *s);
unsigned int comedi_buf_write_n_allocated(struct comedi_async *async);
void comedi_device_cancel_all(struct comedi_device *dev);
diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c
index 71db683098d6..b59af0303581 100644
--- a/drivers/staging/comedi/drivers/usbdux.c
+++ b/drivers/staging/comedi/drivers/usbdux.c
@@ -493,7 +493,7 @@ static void usbduxsub_ao_isoc_irq(struct urb *urb)
/* pointer to the DA */
*datap++ = val & 0xff;
*datap++ = (val >> 8) & 0xff;
- *datap++ = chan;
+ *datap++ = chan << 6;
devpriv->ao_readback[chan] = val;
s->async->events |= COMEDI_CB_BLOCK;
@@ -1040,11 +1040,8 @@ static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
/* set current channel of the running acquisition to zero */
s->async->cur_chan = 0;
- for (i = 0; i < cmd->chanlist_len; ++i) {
- unsigned int chan = CR_CHAN(cmd->chanlist[i]);
-
- devpriv->ao_chanlist[i] = chan << 6;
- }
+ for (i = 0; i < cmd->chanlist_len; ++i)
+ devpriv->ao_chanlist[i] = CR_CHAN(cmd->chanlist[i]);
/* we count in steps of 1ms (125us) */
/* 125us mode not used yet */
diff --git a/drivers/staging/goldfish/goldfish_audio.c b/drivers/staging/goldfish/goldfish_audio.c
index f96dcec740ae..7ac2602242f1 100644
--- a/drivers/staging/goldfish/goldfish_audio.c
+++ b/drivers/staging/goldfish/goldfish_audio.c
@@ -334,6 +334,7 @@ static int goldfish_audio_probe(struct platform_device *pdev)
return 0;
err_misc_register_failed:
+ free_irq(data->irq, data);
err_request_irq_failed:
dma_free_coherent(&pdev->dev, COMBINED_BUFFER_SIZE,
data->buffer_virt, data->buffer_phys);
diff --git a/drivers/staging/gs_fpgaboot/Makefile b/drivers/staging/gs_fpgaboot/Makefile
index 34cb606e0e3d..d2f0211ba540 100644
--- a/drivers/staging/gs_fpgaboot/Makefile
+++ b/drivers/staging/gs_fpgaboot/Makefile
@@ -1,4 +1,2 @@
gs_fpga-y += gs_fpgaboot.o io.o
obj-$(CONFIG_GS_FPGABOOT) += gs_fpga.o
-
-ccflags-$(CONFIG_GS_FPGA_DEBUG) := -DDEBUG
diff --git a/drivers/staging/gs_fpgaboot/gs_fpgaboot.c b/drivers/staging/gs_fpgaboot/gs_fpgaboot.c
index 89bc84d833e6..7506900c9b8d 100644
--- a/drivers/staging/gs_fpgaboot/gs_fpgaboot.c
+++ b/drivers/staging/gs_fpgaboot/gs_fpgaboot.c
@@ -373,7 +373,6 @@ static int __init gs_fpgaboot_init(void)
r = -1;
pr_info("FPGA DOWNLOAD --->\n");
- pr_info("built at %s UTC\n", __TIMESTAMP__);
pr_info("FPGA image file name: %s\n", file);
diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c
index 11fb95201545..dae8d1a9038e 100644
--- a/drivers/staging/iio/adc/mxs-lradc.c
+++ b/drivers/staging/iio/adc/mxs-lradc.c
@@ -1526,7 +1526,7 @@ static int mxs_lradc_probe(struct platform_device *pdev)
struct resource *iores;
int ret = 0, touch_ret;
int i, s;
- unsigned int scale_uv;
+ uint64_t scale_uv;
/* Allocate the IIO device. */
iio = devm_iio_device_alloc(dev, sizeof(*lradc));
diff --git a/drivers/staging/iio/resolver/ad2s1200.c b/drivers/staging/iio/resolver/ad2s1200.c
index 36eedd8a0ea9..017d2f8379b7 100644
--- a/drivers/staging/iio/resolver/ad2s1200.c
+++ b/drivers/staging/iio/resolver/ad2s1200.c
@@ -70,6 +70,7 @@ static int ad2s1200_read_raw(struct iio_dev *indio_dev,
vel = (((s16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4);
vel = (vel << 4) >> 4;
*val = vel;
+ break;
default:
mutex_unlock(&st->lock);
return -EINVAL;
@@ -106,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) {
@@ -114,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;
diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c
index 4144a75e5f71..c270c9ae6d27 100644
--- a/drivers/staging/imx-drm/imx-drm-core.c
+++ b/drivers/staging/imx-drm/imx-drm-core.c
@@ -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);
diff --git a/drivers/staging/imx-drm/imx-tve.c b/drivers/staging/imx-drm/imx-tve.c
index 575533f4fd64..a23f4f773146 100644
--- a/drivers/staging/imx-drm/imx-tve.c
+++ b/drivers/staging/imx-drm/imx-tve.c
@@ -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);
diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c
index 8c101cbbee97..acc8184c46cd 100644
--- a/drivers/staging/media/davinci_vpfe/vpfe_video.c
+++ b/drivers/staging/media/davinci_vpfe/vpfe_video.c
@@ -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);
diff --git a/drivers/staging/media/sn9c102/sn9c102_devtable.h b/drivers/staging/media/sn9c102/sn9c102_devtable.h
index b3d2cc729657..4ba569258498 100644
--- a/drivers/staging/media/sn9c102/sn9c102_devtable.h
+++ b/drivers/staging/media/sn9c102/sn9c102_devtable.h
@@ -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), },
diff --git a/drivers/staging/rtl8187se/Kconfig b/drivers/staging/rtl8187se/Kconfig
deleted file mode 100644
index ff8d41ebca36..000000000000
--- a/drivers/staging/rtl8187se/Kconfig
+++ /dev/null
@@ -1,10 +0,0 @@
-config R8187SE
- tristate "RealTek RTL8187SE Wireless LAN NIC driver"
- depends on PCI && WLAN
- depends on m
- select WIRELESS_EXT
- select WEXT_PRIV
- select EEPROM_93CX6
- select CRYPTO
- ---help---
- If built as a module, it will be called r8187se.ko.
diff --git a/drivers/staging/rtl8187se/Makefile b/drivers/staging/rtl8187se/Makefile
deleted file mode 100644
index 91d1aa2830c9..000000000000
--- a/drivers/staging/rtl8187se/Makefile
+++ /dev/null
@@ -1,38 +0,0 @@
-
-#ccflags-y += -DCONFIG_IEEE80211_NOWEP=y
-#ccflags-y += -std=gnu89
-#ccflags-y += -O2
-#CC = gcc
-
-ccflags-y := -DSW_ANTE
-ccflags-y += -DTX_TRACK
-ccflags-y += -DHIGH_POWER
-ccflags-y += -DSW_DIG
-ccflags-y += -DRATE_ADAPT
-
-#enable it for legacy power save, disable it for leisure power save
-ccflags-y += -DENABLE_LPS
-
-
-#ccflags-y := -mhard-float -DCONFIG_FORCE_HARD_FLOAT=y
-
-r8187se-y := \
- r8180_core.o \
- r8180_wx.o \
- r8180_rtl8225z2.o \
- r8185b_init.o \
- r8180_dm.o \
- ieee80211/dot11d.o \
- ieee80211/ieee80211_softmac.o \
- ieee80211/ieee80211_rx.o \
- ieee80211/ieee80211_tx.o \
- ieee80211/ieee80211_wx.o \
- ieee80211/ieee80211_module.o \
- ieee80211/ieee80211_softmac_wx.o \
- ieee80211/ieee80211_crypt.o \
- ieee80211/ieee80211_crypt_tkip.o \
- ieee80211/ieee80211_crypt_ccmp.o \
- ieee80211/ieee80211_crypt_wep.o
-
-obj-$(CONFIG_R8187SE) += r8187se.o
-
diff --git a/drivers/staging/rtl8187se/Module.symvers b/drivers/staging/rtl8187se/Module.symvers
deleted file mode 100644
index e69de29bb2d1..000000000000
--- a/drivers/staging/rtl8187se/Module.symvers
+++ /dev/null
diff --git a/drivers/staging/rtl8187se/TODO b/drivers/staging/rtl8187se/TODO
deleted file mode 100644
index 704949a9da0d..000000000000
--- a/drivers/staging/rtl8187se/TODO
+++ /dev/null
@@ -1,13 +0,0 @@
-TODO:
-- prepare private ieee80211 stack for merge with rtl8192su's version:
- - add hwsec_active flag to struct ieee80211_device
- - add bHwSec flag to cb_desc structure
-- switch to use shared "librtl" instead of private ieee80211 stack
-- switch to use LIB80211
-- switch to use MAC80211
-- use kernel coding style
-- checkpatch.pl fixes
-- sparse fixes
-- integrate with drivers/net/wireless/rtl818x
-
-Please send any patches to Greg Kroah-Hartman <greg@kroah.com>.
diff --git a/drivers/staging/rtl8187se/ieee80211/dot11d.c b/drivers/staging/rtl8187se/ieee80211/dot11d.c
deleted file mode 100644
index 4483c2c0307c..000000000000
--- a/drivers/staging/rtl8187se/ieee80211/dot11d.c
+++ /dev/null
@@ -1,189 +0,0 @@
-#include "dot11d.h"
-
-void Dot11d_Init(struct ieee80211_device *ieee)
-{
- PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee);
-
- pDot11dInfo->bEnabled = 0;
-
- pDot11dInfo->State = DOT11D_STATE_NONE;
- pDot11dInfo->CountryIeLen = 0;
- memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
- memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
- RESET_CIE_WATCHDOG(ieee);
-
- netdev_info(ieee->dev, "Dot11d_Init()\n");
-}
-
-/* Reset to the state as we are just entering a regulatory domain. */
-void Dot11d_Reset(struct ieee80211_device *ieee)
-{
- u32 i;
- PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee);
-
- /* Clear old channel map */
- memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
- memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
- /* Set new channel map */
- for (i = 1; i <= 11; i++)
- (pDot11dInfo->channel_map)[i] = 1;
-
- for (i = 12; i <= 14; i++)
- (pDot11dInfo->channel_map)[i] = 2;
-
- pDot11dInfo->State = DOT11D_STATE_NONE;
- pDot11dInfo->CountryIeLen = 0;
- RESET_CIE_WATCHDOG(ieee);
-}
-
-/*
- * Description:
- * Update country IE from Beacon or Probe Response and configure PHY for
- * operation in the regulatory domain.
- *
- * TODO:
- * Configure Tx power.
- *
- * Assumption:
- * 1. IS_DOT11D_ENABLE() is TRUE.
- * 2. Input IE is an valid one.
- */
-void Dot11d_UpdateCountryIe(struct ieee80211_device *dev, u8 *pTaddr,
- u16 CoutryIeLen, u8 *pCoutryIe)
-{
- PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
- u8 i, j, NumTriples, MaxChnlNum;
- u8 index, MaxTxPowerInDbm;
- PCHNL_TXPOWER_TRIPLE pTriple;
-
- if ((CoutryIeLen - 3)%3 != 0) {
- netdev_info(dev->dev, "Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n");
- Dot11d_Reset(dev);
- return;
- }
-
- memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
- memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
- MaxChnlNum = 0;
- NumTriples = (CoutryIeLen - 3) / 3; /* skip 3-byte country string. */
- pTriple = (PCHNL_TXPOWER_TRIPLE)(pCoutryIe + 3);
- for (i = 0; i < NumTriples; i++) {
- if (MaxChnlNum >= pTriple->FirstChnl) {
- /*
- * It is not in a monotonically increasing order,
- * so stop processing.
- */
- netdev_info(dev->dev,
- "Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n");
- Dot11d_Reset(dev);
- return;
- }
- if (MAX_CHANNEL_NUMBER <
- (pTriple->FirstChnl + pTriple->NumChnls)) {
- /*
- * It is not a valid set of channel id,
- * so stop processing
- */
- netdev_info(dev->dev,
- "Dot11d_UpdateCountryIe(): Invalid country IE, skip it........2\n");
- Dot11d_Reset(dev);
- return;
- }
-
- for (j = 0; j < pTriple->NumChnls; j++) {
- index = pTriple->FirstChnl + j;
- pDot11dInfo->channel_map[index] = 1;
- MaxTxPowerInDbm = pTriple->MaxTxPowerInDbm;
- pDot11dInfo->MaxTxPwrDbmList[index] = MaxTxPowerInDbm;
- MaxChnlNum = pTriple->FirstChnl + j;
- }
-
- pTriple = (PCHNL_TXPOWER_TRIPLE)((u8 *)pTriple + 3);
- }
-#if 1
- netdev_info(dev->dev, "Channel List:");
- for (i = 1; i <= MAX_CHANNEL_NUMBER; i++)
- if (pDot11dInfo->channel_map[i] > 0)
- netdev_info(dev->dev, " %d", i);
- netdev_info(dev->dev, "\n");
-#endif
-
- UPDATE_CIE_SRC(dev, pTaddr);
-
- pDot11dInfo->CountryIeLen = CoutryIeLen;
- memcpy(pDot11dInfo->CountryIeBuf, pCoutryIe, CoutryIeLen);
- pDot11dInfo->State = DOT11D_STATE_LEARNED;
-}
-
-u8 DOT11D_GetMaxTxPwrInDbm(struct ieee80211_device *dev, u8 Channel)
-{
- PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
- u8 MaxTxPwrInDbm = 255;
-
- if (MAX_CHANNEL_NUMBER < Channel) {
- netdev_info(dev->dev, "DOT11D_GetMaxTxPwrInDbm(): Invalid Channel\n");
- return MaxTxPwrInDbm;
- }
- if (pDot11dInfo->channel_map[Channel])
- MaxTxPwrInDbm = pDot11dInfo->MaxTxPwrDbmList[Channel];
-
- return MaxTxPwrInDbm;
-}
-
-
-void DOT11D_ScanComplete(struct ieee80211_device *dev)
-{
- PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
-
- switch (pDot11dInfo->State) {
- case DOT11D_STATE_LEARNED:
- pDot11dInfo->State = DOT11D_STATE_DONE;
- break;
-
- case DOT11D_STATE_DONE:
- if (GET_CIE_WATCHDOG(dev) == 0) {
- /* Reset country IE if previous one is gone. */
- Dot11d_Reset(dev);
- }
- break;
- case DOT11D_STATE_NONE:
- break;
- }
-}
-
-int IsLegalChannel(struct ieee80211_device *dev, u8 channel)
-{
- PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
-
- if (MAX_CHANNEL_NUMBER < channel) {
- netdev_info(dev->dev, "IsLegalChannel(): Invalid Channel\n");
- return 0;
- }
- if (pDot11dInfo->channel_map[channel] > 0)
- return 1;
- return 0;
-}
-
-int ToLegalChannel(struct ieee80211_device *dev, u8 channel)
-{
- PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
- u8 default_chn = 0;
- u32 i = 0;
-
- for (i = 1; i <= MAX_CHANNEL_NUMBER; i++) {
- if (pDot11dInfo->channel_map[i] > 0) {
- default_chn = i;
- break;
- }
- }
-
- if (MAX_CHANNEL_NUMBER < channel) {
- netdev_info(dev->dev, "IsLegalChannel(): Invalid Channel\n");
- return default_chn;
- }
-
- if (pDot11dInfo->channel_map[channel] > 0)
- return channel;
-
- return default_chn;
-}
diff --git a/drivers/staging/rtl8187se/ieee80211/dot11d.h b/drivers/staging/rtl8187se/ieee80211/dot11d.h
deleted file mode 100644
index f996691307bf..000000000000
--- a/drivers/staging/rtl8187se/ieee80211/dot11d.h
+++ /dev/null
@@ -1,71 +0,0 @@
-#ifndef __INC_DOT11D_H
-#define __INC_DOT11D_H
-
-#include "ieee80211.h"
-
-/* #define ENABLE_DOT11D */
-
-/* #define DOT11D_MAX_CHNL_NUM 83 */
-
-typedef struct _CHNL_TXPOWER_TRIPLE {
- u8 FirstChnl;
- u8 NumChnls;
- u8 MaxTxPowerInDbm;
-} CHNL_TXPOWER_TRIPLE, *PCHNL_TXPOWER_TRIPLE;
-
-typedef enum _DOT11D_STATE {
- DOT11D_STATE_NONE = 0,
- DOT11D_STATE_LEARNED,
- DOT11D_STATE_DONE,
-} DOT11D_STATE;
-
-typedef struct _RT_DOT11D_INFO {
- /* DECLARE_RT_OBJECT(RT_DOT12D_INFO); */
-
- bool bEnabled; /* dot11MultiDomainCapabilityEnabled */
-
- u16 CountryIeLen; /* > 0 if CountryIeBuf[] contains valid country information element. */
- u8 CountryIeBuf[MAX_IE_LEN];
- u8 CountryIeSrcAddr[6]; /* Source AP of the country IE. */
- u8 CountryIeWatchdog;
-
- u8 channel_map[MAX_CHANNEL_NUMBER+1]; /* !!!Value 0: Invalid, 1: Valid (active scan), 2: Valid (passive scan) */
- /* u8 ChnlListLen; // #Bytes valid in ChnlList[]. */
- /* u8 ChnlList[DOT11D_MAX_CHNL_NUM]; */
- u8 MaxTxPwrDbmList[MAX_CHANNEL_NUMBER+1];
-
- DOT11D_STATE State;
-} RT_DOT11D_INFO, *PRT_DOT11D_INFO;
-
-#define eqMacAddr(a, b) (((a)[0] == (b)[0] && (a)[1] == (b)[1] && (a)[2] == (b)[2] && (a)[3] == (b)[3] && (a)[4] == (b)[4] && (a)[5] == (b)[5]) ? 1:0)
-#define cpMacAddr(des, src) ((des)[0] = (src)[0], (des)[1] = (src)[1], (des)[2] = (src)[2], (des)[3] = (src)[3], (des)[4] = (src)[4], (des)[5] = (src)[5])
-#define GET_DOT11D_INFO(__pIeeeDev) ((PRT_DOT11D_INFO)((__pIeeeDev)->pDot11dInfo))
-
-#define IS_DOT11D_ENABLE(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->bEnabled
-#define IS_COUNTRY_IE_VALID(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen > 0)
-
-#define IS_EQUAL_CIE_SRC(__pIeeeDev, __pTa) eqMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
-#define UPDATE_CIE_SRC(__pIeeeDev, __pTa) cpMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
-
-#define IS_COUNTRY_IE_CHANGED(__pIeeeDev, __Ie) \
- (((__Ie).Length == 0 || (__Ie).Length != GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen) ? \
- FALSE : \
- (!memcmp(GET_DOT11D_INFO(__pIeeeDev)->CountryIeBuf, (__Ie).Octet, (__Ie).Length)))
-
-#define CIE_WATCHDOG_TH 1
-#define GET_CIE_WATCHDOG(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog
-#define RESET_CIE_WATCHDOG(__pIeeeDev) GET_CIE_WATCHDOG(__pIeeeDev) = 0
-#define UPDATE_CIE_WATCHDOG(__pIeeeDev) ++GET_CIE_WATCHDOG(__pIeeeDev)
-
-#define IS_DOT11D_STATE_DONE(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE)
-
-void Dot11d_Init(struct ieee80211_device *dev);
-void Dot11d_Reset(struct ieee80211_device *dev);
-void Dot11d_UpdateCountryIe(struct ieee80211_device *dev, u8 *pTaddr,
- u16 CoutryIeLen, u8 *pCoutryIe);
-u8 DOT11D_GetMaxTxPwrInDbm(struct ieee80211_device *dev, u8 Channel);
-void DOT11D_ScanComplete(struct ieee80211_device *dev);
-int IsLegalChannel(struct ieee80211_device *dev, u8 channel);
-int ToLegalChannel(struct ieee80211_device *dev, u8 channel);
-
-#endif /* #ifndef __INC_DOT11D_H */
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211.h b/drivers/staging/rtl8187se/ieee80211/ieee80211.h
deleted file mode 100644
index d1763b7b8f27..000000000000
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211.h
+++ /dev/null
@@ -1,1496 +0,0 @@
-/*
- * Merged with mainline ieee80211.h in Aug 2004. Original ieee802_11
- * remains copyright by the original authors
- *
- * Portions of the merged code are based on Host AP (software wireless
- * LAN access point) driver for Intersil Prism2/2.5/3.
- *
- * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
- * <jkmaline@cc.hut.fi>
- * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
- *
- * Adaption to a generic IEEE 802.11 stack by James Ketrenos
- * <jketreno@linux.intel.com>
- * Copyright (c) 2004, Intel Corporation
- *
- * Modified for Realtek's wi-fi cards by Andrea Merello
- * <andrea.merello@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation. See README and COPYING for
- * more details.
- */
-#ifndef IEEE80211_H
-#define IEEE80211_H
-#include <linux/if_ether.h> /* ETH_ALEN */
-#include <linux/kernel.h> /* ARRAY_SIZE */
-#include <linux/jiffies.h>
-#include <linux/timer.h>
-#include <linux/sched.h>
-#include <linux/semaphore.h>
-#include <linux/wireless.h>
-#include <linux/ieee80211.h>
-#include <linux/interrupt.h>
-
-#define KEY_TYPE_NA 0x0
-#define KEY_TYPE_WEP40 0x1
-#define KEY_TYPE_TKIP 0x2
-#define KEY_TYPE_CCMP 0x4
-#define KEY_TYPE_WEP104 0x5
-
-#define aSifsTime 10
-
-#define MGMT_QUEUE_NUM 5
-
-
-#define IEEE_CMD_SET_WPA_PARAM 1
-#define IEEE_CMD_SET_WPA_IE 2
-#define IEEE_CMD_SET_ENCRYPTION 3
-#define IEEE_CMD_MLME 4
-
-#define IEEE_PARAM_WPA_ENABLED 1
-#define IEEE_PARAM_TKIP_COUNTERMEASURES 2
-#define IEEE_PARAM_DROP_UNENCRYPTED 3
-#define IEEE_PARAM_PRIVACY_INVOKED 4
-#define IEEE_PARAM_AUTH_ALGS 5
-#define IEEE_PARAM_IEEE_802_1X 6
-//It should consistent with the driver_XXX.c
-// David, 2006.9.26
-#define IEEE_PARAM_WPAX_SELECT 7
-//Added for notify the encryption type selection
-// David, 2006.9.26
-#define IEEE_PROTO_WPA 1
-#define IEEE_PROTO_RSN 2
-//Added for notify the encryption type selection
-// David, 2006.9.26
-#define IEEE_WPAX_USEGROUP 0
-#define IEEE_WPAX_WEP40 1
-#define IEEE_WPAX_TKIP 2
-#define IEEE_WPAX_WRAP 3
-#define IEEE_WPAX_CCMP 4
-#define IEEE_WPAX_WEP104 5
-
-#define IEEE_KEY_MGMT_IEEE8021X 1
-#define IEEE_KEY_MGMT_PSK 2
-
-
-
-#define IEEE_MLME_STA_DEAUTH 1
-#define IEEE_MLME_STA_DISASSOC 2
-
-
-#define IEEE_CRYPT_ERR_UNKNOWN_ALG 2
-#define IEEE_CRYPT_ERR_UNKNOWN_ADDR 3
-#define IEEE_CRYPT_ERR_CRYPT_INIT_FAILED 4
-#define IEEE_CRYPT_ERR_KEY_SET_FAILED 5
-#define IEEE_CRYPT_ERR_TX_KEY_SET_FAILED 6
-#define IEEE_CRYPT_ERR_CARD_CONF_FAILED 7
-
-
-#define IEEE_CRYPT_ALG_NAME_LEN 16
-
-extern int ieee80211_crypto_tkip_init(void);
-extern void ieee80211_crypto_tkip_exit(void);
-
-//by amy for ps
-typedef struct ieee_param {
- u32 cmd;
- u8 sta_addr[ETH_ALEN];
- union {
- struct {
- u8 name;
- u32 value;
- } wpa_param;
- struct {
- u32 len;
- u8 reserved[32];
- u8 data[0];
- } wpa_ie;
- struct{
- int command;
- int reason_code;
- } mlme;
- struct {
- u8 alg[IEEE_CRYPT_ALG_NAME_LEN];
- u8 set_tx;
- u32 err;
- u8 idx;
- u8 seq[8]; /* sequence counter (set: RX, get: TX) */
- u16 key_len;
- u8 key[0];
- } crypt;
-
- } u;
-}ieee_param;
-
-
-#define MSECS(t) msecs_to_jiffies(t)
-#define msleep_interruptible_rtl msleep_interruptible
-
-#define IEEE80211_DATA_LEN 2304
-/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
- 6.2.1.1.2.
-
- The figure in section 7.1.2 suggests a body size of up to 2312
- bytes is allowed, which is a bit confusing, I suspect this
- represents the 2304 bytes of real data, plus a possible 8 bytes of
- WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */
-
-#define IEEE80211_3ADDR_LEN 24
-#define IEEE80211_4ADDR_LEN 30
-#define IEEE80211_FCS_LEN 4
-#define IEEE80211_HLEN IEEE80211_4ADDR_LEN
-#define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN)
-#define IEEE80211_MGMT_HDR_LEN 24
-#define IEEE80211_DATA_HDR3_LEN 24
-#define IEEE80211_DATA_HDR4_LEN 30
-
-#define MIN_FRAG_THRESHOLD 256U
-#define MAX_FRAG_THRESHOLD 2346U
-
-/* Frame control field constants */
-#define IEEE80211_FCTL_DSTODS 0x0300 //added by david
-#define IEEE80211_FCTL_WEP 0x4000
-
-/* debug macros */
-
-#ifdef CONFIG_IEEE80211_DEBUG
-extern u32 ieee80211_debug_level;
-#define IEEE80211_DEBUG(level, fmt, args...) \
-do { if (ieee80211_debug_level & (level)) \
- printk(KERN_DEBUG "ieee80211: %c %s " fmt, \
- in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0)
-#else
-#define IEEE80211_DEBUG(level, fmt, args...) do {} while (0)
-#endif /* CONFIG_IEEE80211_DEBUG */
-
-/*
- * To use the debug system;
- *
- * If you are defining a new debug classification, simply add it to the #define
- * list here in the form of:
- *
- * #define IEEE80211_DL_xxxx VALUE
- *
- * shifting value to the left one bit from the previous entry. xxxx should be
- * the name of the classification (for example, WEP)
- *
- * You then need to either add a IEEE80211_xxxx_DEBUG() macro definition for your
- * classification, or use IEEE80211_DEBUG(IEEE80211_DL_xxxx, ...) whenever you want
- * to send output to that classification.
- *
- * To add your debug level to the list of levels seen when you perform
- *
- * % cat /proc/net/ipw/debug_level
- *
- * you simply need to add your entry to the ipw_debug_levels array.
- *
- * If you do not see debug_level in /proc/net/ipw then you do not have
- * CONFIG_IEEE80211_DEBUG defined in your kernel configuration
- *
- */
-
-#define IEEE80211_DL_INFO (1<<0)
-#define IEEE80211_DL_WX (1<<1)
-#define IEEE80211_DL_SCAN (1<<2)
-#define IEEE80211_DL_STATE (1<<3)
-#define IEEE80211_DL_MGMT (1<<4)
-#define IEEE80211_DL_FRAG (1<<5)
-#define IEEE80211_DL_EAP (1<<6)
-#define IEEE80211_DL_DROP (1<<7)
-
-#define IEEE80211_DL_TX (1<<8)
-#define IEEE80211_DL_RX (1<<9)
-
-#define IEEE80211_ERROR(f, a...) printk(KERN_ERR "ieee80211: " f, ## a)
-#define IEEE80211_WARNING(f, a...) printk(KERN_WARNING "ieee80211: " f, ## a)
-#define IEEE80211_DEBUG_INFO(f, a...) IEEE80211_DEBUG(IEEE80211_DL_INFO, f, ## a)
-
-#define IEEE80211_DEBUG_WX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_WX, f, ## a)
-#define IEEE80211_DEBUG_SCAN(f, a...) IEEE80211_DEBUG(IEEE80211_DL_SCAN, f, ## a)
-//#define IEEE_DEBUG_SCAN IEEE80211_WARNING
-#define IEEE80211_DEBUG_STATE(f, a...) IEEE80211_DEBUG(IEEE80211_DL_STATE, f, ## a)
-#define IEEE80211_DEBUG_MGMT(f, a...) IEEE80211_DEBUG(IEEE80211_DL_MGMT, f, ## a)
-#define IEEE80211_DEBUG_FRAG(f, a...) IEEE80211_DEBUG(IEEE80211_DL_FRAG, f, ## a)
-#define IEEE80211_DEBUG_EAP(f, a...) IEEE80211_DEBUG(IEEE80211_DL_EAP, f, ## a)
-#define IEEE80211_DEBUG_DROP(f, a...) IEEE80211_DEBUG(IEEE80211_DL_DROP, f, ## a)
-#define IEEE80211_DEBUG_TX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_TX, f, ## a)
-#define IEEE80211_DEBUG_RX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_RX, f, ## a)
-#include <linux/netdevice.h>
-#include <linux/if_arp.h> /* ARPHRD_ETHER */
-
-#ifndef WIRELESS_SPY
-#define WIRELESS_SPY // enable iwspy support
-#endif
-#include <net/iw_handler.h> // new driver API
-
-#ifndef ETH_P_PAE
-#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */
-#endif /* ETH_P_PAE */
-
-#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */
-
-#ifndef ETH_P_80211_RAW
-#define ETH_P_80211_RAW (ETH_P_ECONET + 1)
-#endif
-
-/* IEEE 802.11 defines */
-
-#define P80211_OUI_LEN 3
-
-struct ieee80211_snap_hdr {
-
- u8 dsap; /* always 0xAA */
- u8 ssap; /* always 0xAA */
- u8 ctrl; /* always 0x03 */
- u8 oui[P80211_OUI_LEN]; /* organizational universal id */
-
-} __attribute__ ((packed));
-
-#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr)
-
-#define WLAN_FC_GET_TYPE(fc) ((fc) & IEEE80211_FCTL_FTYPE)
-#define WLAN_FC_GET_STYPE(fc) ((fc) & IEEE80211_FCTL_STYPE)
-
-#define WLAN_GET_SEQ_FRAG(seq) ((seq) & IEEE80211_SCTL_FRAG)
-#define WLAN_GET_SEQ_SEQ(seq) ((seq) & IEEE80211_SCTL_SEQ)
-
-#define WLAN_CAPABILITY_BSS (1<<0)
-#define WLAN_CAPABILITY_SHORT_SLOT (1<<10)
-
-#define IEEE80211_STATMASK_SIGNAL (1<<0)
-#define IEEE80211_STATMASK_RSSI (1<<1)
-#define IEEE80211_STATMASK_NOISE (1<<2)
-#define IEEE80211_STATMASK_RATE (1<<3)
-#define IEEE80211_STATMASK_WEMASK 0x7
-
-
-#define IEEE80211_CCK_MODULATION (1<<0)
-#define IEEE80211_OFDM_MODULATION (1<<1)
-
-#define IEEE80211_24GHZ_BAND (1<<0)
-#define IEEE80211_52GHZ_BAND (1<<1)
-
-#define IEEE80211_CCK_RATE_LEN 4
-#define IEEE80211_CCK_RATE_1MB 0x02
-#define IEEE80211_CCK_RATE_2MB 0x04
-#define IEEE80211_CCK_RATE_5MB 0x0B
-#define IEEE80211_CCK_RATE_11MB 0x16
-#define IEEE80211_OFDM_RATE_LEN 8
-#define IEEE80211_OFDM_RATE_6MB 0x0C
-#define IEEE80211_OFDM_RATE_9MB 0x12
-#define IEEE80211_OFDM_RATE_12MB 0x18
-#define IEEE80211_OFDM_RATE_18MB 0x24
-#define IEEE80211_OFDM_RATE_24MB 0x30
-#define IEEE80211_OFDM_RATE_36MB 0x48
-#define IEEE80211_OFDM_RATE_48MB 0x60
-#define IEEE80211_OFDM_RATE_54MB 0x6C
-#define IEEE80211_BASIC_RATE_MASK 0x80
-
-#define IEEE80211_CCK_RATE_1MB_MASK (1<<0)
-#define IEEE80211_CCK_RATE_2MB_MASK (1<<1)
-#define IEEE80211_CCK_RATE_5MB_MASK (1<<2)
-#define IEEE80211_CCK_RATE_11MB_MASK (1<<3)
-#define IEEE80211_OFDM_RATE_6MB_MASK (1<<4)
-#define IEEE80211_OFDM_RATE_9MB_MASK (1<<5)
-#define IEEE80211_OFDM_RATE_12MB_MASK (1<<6)
-#define IEEE80211_OFDM_RATE_18MB_MASK (1<<7)
-#define IEEE80211_OFDM_RATE_24MB_MASK (1<<8)
-#define IEEE80211_OFDM_RATE_36MB_MASK (1<<9)
-#define IEEE80211_OFDM_RATE_48MB_MASK (1<<10)
-#define IEEE80211_OFDM_RATE_54MB_MASK (1<<11)
-
-#define IEEE80211_CCK_RATES_MASK 0x0000000F
-#define IEEE80211_CCK_BASIC_RATES_MASK (IEEE80211_CCK_RATE_1MB_MASK | \
- IEEE80211_CCK_RATE_2MB_MASK)
-#define IEEE80211_CCK_DEFAULT_RATES_MASK (IEEE80211_CCK_BASIC_RATES_MASK | \
- IEEE80211_CCK_RATE_5MB_MASK | \
- IEEE80211_CCK_RATE_11MB_MASK)
-
-#define IEEE80211_OFDM_RATES_MASK 0x00000FF0
-#define IEEE80211_OFDM_BASIC_RATES_MASK (IEEE80211_OFDM_RATE_6MB_MASK | \
- IEEE80211_OFDM_RATE_12MB_MASK | \
- IEEE80211_OFDM_RATE_24MB_MASK)
-#define IEEE80211_OFDM_DEFAULT_RATES_MASK (IEEE80211_OFDM_BASIC_RATES_MASK | \
- IEEE80211_OFDM_RATE_9MB_MASK | \
- IEEE80211_OFDM_RATE_18MB_MASK | \
- IEEE80211_OFDM_RATE_36MB_MASK | \
- IEEE80211_OFDM_RATE_48MB_MASK | \
- IEEE80211_OFDM_RATE_54MB_MASK)
-#define IEEE80211_DEFAULT_RATES_MASK (IEEE80211_OFDM_DEFAULT_RATES_MASK | \
- IEEE80211_CCK_DEFAULT_RATES_MASK)
-
-#define IEEE80211_NUM_OFDM_RATES 8
-#define IEEE80211_NUM_CCK_RATES 4
-#define IEEE80211_OFDM_SHIFT_MASK_A 4
-
-/* this is stolen and modified from the madwifi driver*/
-#define IEEE80211_FC0_TYPE_MASK 0x0c
-#define IEEE80211_FC0_TYPE_DATA 0x08
-#define IEEE80211_FC0_SUBTYPE_MASK 0xB0
-#define IEEE80211_FC0_SUBTYPE_QOS 0x80
-
-#define IEEE80211_QOS_HAS_SEQ(fc) \
- (((fc) & (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == \
- (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS))
-
-/* this is stolen from ipw2200 driver */
-#define IEEE_IBSS_MAC_HASH_SIZE 31
-struct ieee_ibss_seq {
- u8 mac[ETH_ALEN];
- u16 seq_num[17];
- u16 frag_num[17];
- unsigned long packet_time[17];
- struct list_head list;
-};
-
-/* NOTE: This data is for statistical purposes; not all hardware provides this
- * information for frames received. Not setting these will not cause
- * any adverse affects. */
-struct ieee80211_rx_stats {
- u32 mac_time[2];
- u8 signalstrength;
- s8 rssi;
- u8 signal;
- u8 noise;
- u16 rate; /* in 100 kbps */
- u8 received_channel;
- u8 control;
- u8 mask;
- u8 freq;
- u16 len;
- u8 nic_type;
-};
-
-/* IEEE 802.11 requires that STA supports concurrent reception of at least
- * three fragmented frames. This define can be increased to support more
- * concurrent frames, but it should be noted that each entry can consume about
- * 2 kB of RAM and increasing cache size will slow down frame reassembly. */
-#define IEEE80211_FRAG_CACHE_LEN 4
-
-struct ieee80211_frag_entry {
- unsigned long first_frag_time;
- unsigned int seq;
- unsigned int last_frag;
- struct sk_buff *skb;
- u8 src_addr[ETH_ALEN];
- u8 dst_addr[ETH_ALEN];
-};
-
-struct ieee80211_stats {
- unsigned int tx_unicast_frames;
- unsigned int tx_multicast_frames;
- unsigned int tx_fragments;
- unsigned int tx_unicast_octets;
- unsigned int tx_multicast_octets;
- unsigned int tx_deferred_transmissions;
- unsigned int tx_single_retry_frames;
- unsigned int tx_multiple_retry_frames;
- unsigned int tx_retry_limit_exceeded;
- unsigned int tx_discards;
- unsigned int rx_unicast_frames;
- unsigned int rx_multicast_frames;
- unsigned int rx_fragments;
- unsigned int rx_unicast_octets;
- unsigned int rx_multicast_octets;
- unsigned int rx_fcs_errors;
- unsigned int rx_discards_no_buffer;
- unsigned int tx_discards_wrong_sa;
- unsigned int rx_discards_undecryptable;
- unsigned int rx_message_in_msg_fragments;
- unsigned int rx_message_in_bad_msg_fragments;
-};
-
-struct ieee80211_device;
-
-#include "ieee80211_crypt.h"
-
-#define SEC_KEY_1 (1<<0)
-#define SEC_KEY_2 (1<<1)
-#define SEC_KEY_3 (1<<2)
-#define SEC_KEY_4 (1<<3)
-#define SEC_ACTIVE_KEY (1<<4)
-#define SEC_AUTH_MODE (1<<5)
-#define SEC_UNICAST_GROUP (1<<6)
-#define SEC_LEVEL (1<<7)
-#define SEC_ENABLED (1<<8)
-
-#define SEC_LEVEL_0 0 /* None */
-#define SEC_LEVEL_1 1 /* WEP 40 and 104 bit */
-#define SEC_LEVEL_2 2 /* Level 1 + TKIP */
-#define SEC_LEVEL_2_CKIP 3 /* Level 1 + CKIP */
-#define SEC_LEVEL_3 4 /* Level 2 + CCMP */
-
-#define WEP_KEYS 4
-#define WEP_KEY_LEN 13
-
-#define WEP_KEY_LEN_MODIF 32
-
-struct ieee80211_security {
- u16 active_key:2,
- enabled:1,
- auth_mode:2,
- auth_algo:4,
- unicast_uses_group:1;
- u8 key_sizes[WEP_KEYS];
- u8 keys[WEP_KEYS][WEP_KEY_LEN_MODIF];
- u8 level;
- u16 flags;
-} __attribute__ ((packed));
-
-
-/*
-
- 802.11 data frame from AP
-
- ,-------------------------------------------------------------------.
-Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 |
- |------|------|---------|---------|---------|------|---------|------|
-Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | frame | fcs |
- | | tion | (BSSID) | | | ence | data | |
- `-------------------------------------------------------------------'
-
-Total: 28-2340 bytes
-
-*/
-
-/* Management Frame Information Element Types */
-enum {
- MFIE_TYPE_SSID = 0,
- MFIE_TYPE_RATES = 1,
- MFIE_TYPE_FH_SET = 2,
- MFIE_TYPE_DS_SET = 3,
- MFIE_TYPE_CF_SET = 4,
- MFIE_TYPE_TIM = 5,
- MFIE_TYPE_IBSS_SET = 6,
- MFIE_TYPE_COUNTRY = 7,
- MFIE_TYPE_CHALLENGE = 16,
- MFIE_TYPE_ERP = 42,
- MFIE_TYPE_RSN = 48,
- MFIE_TYPE_RATES_EX = 50,
- MFIE_TYPE_GENERIC = 221,
-};
-
-struct ieee80211_header_data {
- __le16 frame_ctl;
- u16 duration_id;
- u8 addr1[6];
- u8 addr2[6];
- u8 addr3[6];
- u16 seq_ctrl;
-};
-
-struct ieee80211_hdr_4addr {
- __le16 frame_ctl;
- u16 duration_id;
- u8 addr1[ETH_ALEN];
- u8 addr2[ETH_ALEN];
- u8 addr3[ETH_ALEN];
- u16 seq_ctl;
- u8 addr4[ETH_ALEN];
-} __attribute__ ((packed));
-
-struct ieee80211_hdr_3addrqos {
- u16 frame_ctl;
- u16 duration_id;
- u8 addr1[ETH_ALEN];
- u8 addr2[ETH_ALEN];
- u8 addr3[ETH_ALEN];
- u16 seq_ctl;
- u16 qos_ctl;
-} __attribute__ ((packed));
-
-struct ieee80211_hdr_4addrqos {
- u16 frame_ctl;
- u16 duration_id;
- u8 addr1[ETH_ALEN];
- u8 addr2[ETH_ALEN];
- u8 addr3[ETH_ALEN];
- u16 seq_ctl;
- u8 addr4[ETH_ALEN];
- u16 qos_ctl;
-} __attribute__ ((packed));
-
-struct ieee80211_info_element_hdr {
- u8 id;
- u8 len;
-} __attribute__ ((packed));
-
-struct ieee80211_info_element {
- u8 id;
- u8 len;
- u8 data[0];
-} __attribute__ ((packed));
-
-struct ieee80211_authentication {
- struct ieee80211_header_data header;
- u16 algorithm;
- u16 transaction;
- u16 status;
- //struct ieee80211_info_element_hdr info_element;
-} __attribute__ ((packed));
-
-struct ieee80211_disassoc_frame {
- struct ieee80211_hdr_3addr header;
- u16 reasoncode;
-} __attribute__ ((packed));
-
-struct ieee80211_probe_request {
- struct ieee80211_header_data header;
- /* struct ieee80211_info_element info_element; */
-} __attribute__ ((packed));
-
-struct ieee80211_probe_response {
- struct ieee80211_header_data header;
- u32 time_stamp[2];
- u16 beacon_interval;
- u16 capability;
- struct ieee80211_info_element info_element;
-} __attribute__ ((packed));
-
-struct ieee80211_assoc_request_frame {
- struct ieee80211_hdr_3addr header;
- u16 capability;
- u16 listen_interval;
- //u8 current_ap[ETH_ALEN];
- struct ieee80211_info_element_hdr info_element;
-} __attribute__ ((packed));
-
-struct ieee80211_assoc_response_frame {
- struct ieee80211_hdr_3addr header;
- u16 capability;
- u16 status;
- u16 aid;
- struct ieee80211_info_element info_element; /* supported rates */
-} __attribute__ ((packed));
-
-struct ieee80211_txb {
- u8 nr_frags;
- u8 encrypted;
- u16 reserved;
- u16 frag_size;
- u16 payload_size;
- struct sk_buff *fragments[0];
-};
-
-/* SWEEP TABLE ENTRIES NUMBER */
-#define MAX_SWEEP_TAB_ENTRIES 42
-#define MAX_SWEEP_TAB_ENTRIES_PER_PACKET 7
-
-/* MAX_RATES_LENGTH needs to be 12. The spec says 8, and many APs
- * only use 8, and then use extended rates for the remaining supported
- * rates. Other APs, however, stick all of their supported rates on the
- * main rates information element... */
-#define MAX_RATES_LENGTH ((u8)12)
-#define MAX_RATES_EX_LENGTH ((u8)16)
-
-#define MAX_NETWORK_COUNT 128
-
-#define MAX_CHANNEL_NUMBER 165
-
-#define IEEE80211_SOFTMAC_SCAN_TIME 100 /* (HZ / 2) */
-#define IEEE80211_SOFTMAC_ASSOC_RETRY_TIME (HZ * 2)
-
-#define CRC_LENGTH 4U
-
-#define MAX_WPA_IE_LEN 64
-
-#define NETWORK_EMPTY_ESSID (1 << 0)
-#define NETWORK_HAS_OFDM (1 << 1)
-#define NETWORK_HAS_CCK (1 << 2)
-
-struct ieee80211_wmm_ac_param {
- u8 ac_aci_acm_aifsn;
- u8 ac_ecwmin_ecwmax;
- u16 ac_txop_limit;
-};
-
-struct ieee80211_wmm_ts_info {
- u8 ac_dir_tid;
- u8 ac_up_psb;
- u8 reserved;
-} __attribute__ ((packed));
-
-struct ieee80211_wmm_tspec_elem {
- struct ieee80211_wmm_ts_info ts_info;
- u16 norm_msdu_size;
- u16 max_msdu_size;
- u32 min_serv_inter;
- u32 max_serv_inter;
- u32 inact_inter;
- u32 suspen_inter;
- u32 serv_start_time;
- u32 min_data_rate;
- u32 mean_data_rate;
- u32 peak_data_rate;
- u32 max_burst_size;
- u32 delay_bound;
- u32 min_phy_rate;
- u16 surp_band_allow;
- u16 medium_time;
-}__attribute__((packed));
-
-enum eap_type {
- EAP_PACKET = 0,
- EAPOL_START,
- EAPOL_LOGOFF,
- EAPOL_KEY,
- EAPOL_ENCAP_ASF_ALERT
-};
-
-static const char *eap_types[] = {
- [EAP_PACKET] = "EAP-Packet",
- [EAPOL_START] = "EAPOL-Start",
- [EAPOL_LOGOFF] = "EAPOL-Logoff",
- [EAPOL_KEY] = "EAPOL-Key",
- [EAPOL_ENCAP_ASF_ALERT] = "EAPOL-Encap-ASF-Alert"
-};
-
-static inline const char *eap_get_type(int type)
-{
- return (type >= ARRAY_SIZE(eap_types)) ? "Unknown" : eap_types[type];
-}
-
-struct eapol {
- u8 snap[6];
- u16 ethertype;
- u8 version;
- u8 type;
- u16 length;
-} __attribute__ ((packed));
-
-struct ieee80211_softmac_stats {
- unsigned int rx_ass_ok;
- unsigned int rx_ass_err;
- unsigned int rx_probe_rq;
- unsigned int tx_probe_rs;
- unsigned int tx_beacons;
- unsigned int rx_auth_rq;
- unsigned int rx_auth_rs_ok;
- unsigned int rx_auth_rs_err;
- unsigned int tx_auth_rq;
- unsigned int no_auth_rs;
- unsigned int no_ass_rs;
- unsigned int tx_ass_rq;
- unsigned int rx_ass_rq;
- unsigned int tx_probe_rq;
- unsigned int reassoc;
- unsigned int swtxstop;
- unsigned int swtxawake;
-};
-
-#define BEACON_PROBE_SSID_ID_POSITION 12
-
-/*
- * These are the data types that can make up management packets
- *
- u16 auth_algorithm;
- u16 auth_sequence;
- u16 beacon_interval;
- u16 capability;
- u8 current_ap[ETH_ALEN];
- u16 listen_interval;
- struct {
- u16 association_id:14, reserved:2;
- } __attribute__ ((packed));
- u32 time_stamp[2];
- u16 reason;
- u16 status;
-*/
-
-#define IEEE80211_DEFAULT_TX_ESSID "Penguin"
-#define IEEE80211_DEFAULT_BASIC_RATE 10
-
-enum {WMM_all_frame, WMM_two_frame, WMM_four_frame, WMM_six_frame};
-#define MAX_SP_Len (WMM_all_frame << 4)
-#define IEEE80211_QOS_TID 0x0f
-#define QOS_CTL_NOTCONTAIN_ACK (0x01 << 5)
-
-#define MAX_IE_LEN 0xFF //+YJ,080625
-
-struct rtl8187se_channel_list {
- u8 channel[MAX_CHANNEL_NUMBER + 1];
- u8 len;
-};
-
-//by amy for ps
-#define IEEE80211_WATCH_DOG_TIME 2000
-//by amy for ps
-//by amy for antenna
-#define ANTENNA_DIVERSITY_TIMER_PERIOD 1000 // 1000 m
-//by amy for antenna
-
-#define IEEE80211_DTIM_MBCAST 4
-#define IEEE80211_DTIM_UCAST 2
-#define IEEE80211_DTIM_VALID 1
-#define IEEE80211_DTIM_INVALID 0
-
-#define IEEE80211_PS_DISABLED 0
-#define IEEE80211_PS_UNICAST IEEE80211_DTIM_UCAST
-#define IEEE80211_PS_MBCAST IEEE80211_DTIM_MBCAST
-#define IEEE80211_PS_ENABLE IEEE80211_DTIM_VALID
-//added by David for QoS 2006/6/30
-//#define WMM_Hang_8187
-#ifdef WMM_Hang_8187
-#undef WMM_Hang_8187
-#endif
-
-#define WME_AC_BE 0x00
-#define WME_AC_BK 0x01
-#define WME_AC_VI 0x02
-#define WME_AC_VO 0x03
-#define WME_ACI_MASK 0x03
-#define WME_AIFSN_MASK 0x03
-#define WME_AC_PRAM_LEN 16
-
-//UP Mapping to AC, using in MgntQuery_SequenceNumber() and maybe for DSCP
-//#define UP2AC(up) ((up<3) ? ((up==0)?1:0) : (up>>1))
-#define UP2AC(up) ( \
- ((up) < 1) ? WME_AC_BE : \
- ((up) < 3) ? WME_AC_BK : \
- ((up) < 4) ? WME_AC_BE : \
- ((up) < 6) ? WME_AC_VI : \
- WME_AC_VO)
-//AC Mapping to UP, using in Tx part for selecting the corresponding TX queue
-#define AC2UP(_ac) ( \
- ((_ac) == WME_AC_VO) ? 6 : \
- ((_ac) == WME_AC_VI) ? 5 : \
- ((_ac) == WME_AC_BK) ? 1 : \
- 0)
-
-#define ETHER_ADDR_LEN 6 /* length of an Ethernet address */
-struct ether_header {
- u8 ether_dhost[ETHER_ADDR_LEN];
- u8 ether_shost[ETHER_ADDR_LEN];
- u16 ether_type;
-} __attribute__((packed));
-
-#ifndef ETHERTYPE_PAE
-#define ETHERTYPE_PAE 0x888e /* EAPOL PAE/802.1x */
-#endif
-#ifndef ETHERTYPE_IP
-#define ETHERTYPE_IP 0x0800 /* IP protocol */
-#endif
-
-struct ieee80211_network {
- /* These entries are used to identify a unique network */
- u8 bssid[ETH_ALEN];
- u8 channel;
- /* Ensure null-terminated for any debug msgs */
- u8 ssid[IW_ESSID_MAX_SIZE + 1];
- u8 ssid_len;
-
- /* These are network statistics */
- struct ieee80211_rx_stats stats;
- u16 capability;
- u8 rates[MAX_RATES_LENGTH];
- u8 rates_len;
- u8 rates_ex[MAX_RATES_EX_LENGTH];
- u8 rates_ex_len;
- unsigned long last_scanned;
- u8 mode;
- u8 flags;
- u32 last_associate;
- u32 time_stamp[2];
- u16 beacon_interval;
- u16 listen_interval;
- u16 atim_window;
- u8 wpa_ie[MAX_WPA_IE_LEN];
- size_t wpa_ie_len;
- u8 rsn_ie[MAX_WPA_IE_LEN];
- size_t rsn_ie_len;
- u8 dtim_period;
- u8 dtim_data;
- u32 last_dtim_sta_time[2];
- struct list_head list;
- //appeded for QoS
- u8 wmm_info;
- struct ieee80211_wmm_ac_param wmm_param[4];
- u8 QoS_Enable;
- u8 SignalStrength;
-//by amy 080312
- u8 HighestOperaRate;
-//by amy 080312
- u8 Turbo_Enable;//enable turbo mode, added by thomas
- u16 CountryIeLen;
- u8 CountryIeBuf[MAX_IE_LEN];
-};
-
-enum ieee80211_state {
-
- /* the card is not linked at all */
- IEEE80211_NOLINK = 0,
-
- /* IEEE80211_ASSOCIATING* are for BSS client mode
- * the driver shall not perform RX filtering unless
- * the state is LINKED.
- * The driver shall just check for the state LINKED and
- * defaults to NOLINK for ALL the other states (including
- * LINKED_SCANNING)
- */
-
- /* the association procedure will start (wq scheduling)*/
- IEEE80211_ASSOCIATING,
- IEEE80211_ASSOCIATING_RETRY,
-
- /* the association procedure is sending AUTH request*/
- IEEE80211_ASSOCIATING_AUTHENTICATING,
-
- /* the association procedure has successfully authenticated
- * and is sending association request
- */
- IEEE80211_ASSOCIATING_AUTHENTICATED,
-
- /* the link is ok. the card associated to a BSS or linked
- * to a ibss cell or acting as an AP and creating the bss
- */
- IEEE80211_LINKED,
-
- /* same as LINKED, but the driver shall apply RX filter
- * rules as we are in NO_LINK mode. As the card is still
- * logically linked, but it is doing a syncro site survey
- * then it will be back to LINKED state.
- */
- IEEE80211_LINKED_SCANNING,
-
-};
-
-#define DEFAULT_MAX_SCAN_AGE (15 * HZ)
-#define DEFAULT_FTS 2346
-
-#define CFG_IEEE80211_RESERVE_FCS (1<<0)
-#define CFG_IEEE80211_COMPUTE_FCS (1<<1)
-
-typedef struct tx_pending_t{
- int frag;
- struct ieee80211_txb *txb;
-}tx_pending_t;
-
-enum {
- COUNTRY_CODE_FCC = 0,
- COUNTRY_CODE_IC = 1,
- COUNTRY_CODE_ETSI = 2,
- COUNTRY_CODE_SPAIN = 3,
- COUNTRY_CODE_FRANCE = 4,
- COUNTRY_CODE_MKK = 5,
- COUNTRY_CODE_MKK1 = 6,
- COUNTRY_CODE_ISRAEL = 7,
- COUNTRY_CODE_TELEC = 8,
- COUNTRY_CODE_GLOBAL_DOMAIN = 9,
- COUNTRY_CODE_WORLD_WIDE_13_INDEX = 10
-};
-
-struct ieee80211_device {
- struct net_device *dev;
-
- /* Bookkeeping structures */
- struct net_device_stats stats;
- struct ieee80211_stats ieee_stats;
- struct ieee80211_softmac_stats softmac_stats;
-
- /* Probe / Beacon management */
- struct list_head network_free_list;
- struct list_head network_list;
- struct ieee80211_network *networks;
- int scans;
- int scan_age;
-
- int iw_mode; /* operating mode (IW_MODE_*) */
-
- spinlock_t lock;
- spinlock_t wpax_suitlist_lock;
-
- int tx_headroom; /* Set to size of any additional room needed at front
- * of allocated Tx SKBs */
- u32 config;
-
- /* WEP and other encryption related settings at the device level */
- int open_wep; /* Set to 1 to allow unencrypted frames */
-
- int reset_on_keychange; /* Set to 1 if the HW needs to be reset on
- * WEP key changes */
-
- /* If the host performs {en,de}cryption, then set to 1 */
- int host_encrypt;
- int host_decrypt;
- int ieee802_1x; /* is IEEE 802.1X used */
-
- /* WPA data */
- int wpa_enabled;
- int drop_unencrypted;
- int tkip_countermeasures;
- int privacy_invoked;
- size_t wpa_ie_len;
- u8 *wpa_ie;
-
- u8 ap_mac_addr[6];
- u16 pairwise_key_type;
- u16 broadcast_key_type;
-
- struct list_head crypt_deinit_list;
- struct ieee80211_crypt_data *crypt[WEP_KEYS];
- int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */
- struct timer_list crypt_deinit_timer;
-
- int bcrx_sta_key; /* use individual keys to override default keys even
- * with RX of broad/multicast frames */
-
- /* Fragmentation structures */
- /* each stream contains an entry */
- struct ieee80211_frag_entry frag_cache[17][IEEE80211_FRAG_CACHE_LEN];
- unsigned int frag_next_idx[17];
- u16 fts; /* Fragmentation Threshold */
-
- /* This stores infos for the current network.
- * Either the network we are associated in INFRASTRUCTURE
- * or the network that we are creating in MASTER mode.
- * ad-hoc is a mixture ;-).
- * Note that in infrastructure mode, even when not associated,
- * fields bssid and essid may be valid (if wpa_set and essid_set
- * are true) as thy carry the value set by the user via iwconfig
- */
- struct ieee80211_network current_network;
-
-
- enum ieee80211_state state;
-
- int short_slot;
- int mode; /* A, B, G */
- int modulation; /* CCK, OFDM */
- int freq_band; /* 2.4Ghz, 5.2Ghz, Mixed */
- int abg_true; /* ABG flag */
-
- /* used for forcing the ibss workqueue to terminate
- * without wait for the syncro scan to terminate
- */
- short sync_scan_hurryup;
-
- void * pDot11dInfo;
- bool bGlobalDomain;
-
- // For Liteon Ch12~13 passive scan
- u8 MinPassiveChnlNum;
- u8 IbssStartChnl;
-
- int rate; /* current rate */
- int basic_rate;
- //FIXME: please callback, see if redundant with softmac_features
- short active_scan;
-
- /* this contains flags for selectively enable softmac support */
- u16 softmac_features;
-
- /* if the sequence control field is not filled by HW */
- u16 seq_ctrl[5];
-
- /* association procedure transaction sequence number */
- u16 associate_seq;
-
- /* AID for RTXed association responses */
- u16 assoc_id;
-
- /* power save mode related*/
- short ps;
- short sta_sleep;
- int ps_timeout;
- struct tasklet_struct ps_task;
- u32 ps_th;
- u32 ps_tl;
-
- short raw_tx;
- /* used if IEEE_SOFTMAC_TX_QUEUE is set */
- short queue_stop;
- short scanning;
- short proto_started;
-
- struct semaphore wx_sem;
- struct semaphore scan_sem;
-
- spinlock_t mgmt_tx_lock;
- spinlock_t beacon_lock;
-
- short beacon_txing;
-
- short wap_set;
- short ssid_set;
-
- u8 wpax_type_set; //{added by David, 2006.9.28}
- u32 wpax_type_notify; //{added by David, 2006.9.26}
-
- /* QoS related flag */
- char init_wmmparam_flag;
-
- /* for discarding duplicated packets in IBSS */
- struct list_head ibss_mac_hash[IEEE_IBSS_MAC_HASH_SIZE];
-
- /* for discarding duplicated packets in BSS */
- u16 last_rxseq_num[17]; /* rx seq previous per-tid */
- u16 last_rxfrag_num[17];/* tx frag previous per-tid */
- unsigned long last_packet_time[17];
-
- /* for PS mode */
- unsigned long last_rx_ps_time;
-
- /* used if IEEE_SOFTMAC_SINGLE_QUEUE is set */
- struct sk_buff *mgmt_queue_ring[MGMT_QUEUE_NUM];
- int mgmt_queue_head;
- int mgmt_queue_tail;
-
-
- /* used if IEEE_SOFTMAC_TX_QUEUE is set */
- struct tx_pending_t tx_pending;
-
- /* used if IEEE_SOFTMAC_ASSOCIATE is set */
- struct timer_list associate_timer;
-
- /* used if IEEE_SOFTMAC_BEACONS is set */
- struct timer_list beacon_timer;
-
- struct work_struct associate_complete_wq;
-// struct work_struct associate_retry_wq;
- struct work_struct associate_procedure_wq;
-// struct work_struct softmac_scan_wq;
- struct work_struct wx_sync_scan_wq;
- struct work_struct wmm_param_update_wq;
- struct work_struct ps_request_tx_ack_wq;//for ps
-// struct work_struct hw_wakeup_wq;
-// struct work_struct hw_sleep_wq;
-// struct work_struct watch_dog_wq;
- bool bInactivePs;
- bool actscanning;
- bool beinretry;
- u16 ListenInterval;
- unsigned long NumRxDataInPeriod; //YJ,add,080828
- unsigned long NumRxBcnInPeriod; //YJ,add,080828
- unsigned long NumRxOkTotal;
- unsigned long NumRxUnicast;//YJ,add,080828,for keep alive
- bool bHwRadioOff;
- struct delayed_work softmac_scan_wq;
- struct delayed_work associate_retry_wq;
- struct delayed_work hw_wakeup_wq;
- struct delayed_work hw_sleep_wq;//+by amy 080324
- struct delayed_work watch_dog_wq;
- struct delayed_work sw_antenna_wq;
- struct delayed_work start_ibss_wq;
-//by amy for rate adaptive 080312
- struct delayed_work rate_adapter_wq;
-//by amy for rate adaptive
- struct delayed_work hw_dig_wq;
- struct delayed_work tx_pw_wq;
-
-//Added for RF power on power off by lizhaoming 080512
- struct delayed_work GPIOChangeRFWorkItem;
-
- struct workqueue_struct *wq;
-
- /* Callback functions */
- void (*set_security)(struct net_device *dev,
- struct ieee80211_security *sec);
-
- /* Used to TX data frame by using txb structs.
- * this is not used if in the softmac_features
- * is set the flag IEEE_SOFTMAC_TX_QUEUE
- */
- int (*hard_start_xmit)(struct ieee80211_txb *txb,
- struct net_device *dev);
-
- int (*reset_port)(struct net_device *dev);
-
- /* Softmac-generated frames (management) are TXed via this
- * callback if the flag IEEE_SOFTMAC_SINGLE_QUEUE is
- * not set. As some cards may have different HW queues that
- * one might want to use for data and management frames
- * the option to have two callbacks might be useful.
- * This function can't sleep.
- */
- int (*softmac_hard_start_xmit)(struct sk_buff *skb,
- struct net_device *dev);
-
- /* used instead of hard_start_xmit (not softmac_hard_start_xmit)
- * if the IEEE_SOFTMAC_TX_QUEUE feature is used to TX data
- * frames. If the option IEEE_SOFTMAC_SINGLE_QUEUE is also set
- * then also management frames are sent via this callback.
- * This function can't sleep.
- */
- void (*softmac_data_hard_start_xmit)(struct sk_buff *skb,
- struct net_device *dev,int rate);
-
- /* stops the HW queue for DATA frames. Useful to avoid
- * waste time to TX data frame when we are reassociating
- * This function can sleep.
- */
- void (*data_hard_stop)(struct net_device *dev);
-
- /* OK this is complementar to data_poll_hard_stop */
- void (*data_hard_resume)(struct net_device *dev);
-
- /* ask to the driver to retune the radio .
- * This function can sleep. the driver should ensure
- * the radio has been switched before return.
- */
- void (*set_chan)(struct net_device *dev,short ch);
-
- /* These are not used if the ieee stack takes care of
- * scanning (IEEE_SOFTMAC_SCAN feature set).
- * In this case only the set_chan is used.
- *
- * The syncro version is similar to the start_scan but
- * does not return until all channels has been scanned.
- * this is called in user context and should sleep,
- * it is called in a work_queue when switching to ad-hoc mode
- * or in behalf of iwlist scan when the card is associated
- * and root user ask for a scan.
- * the function stop_scan should stop both the syncro and
- * background scanning and can sleep.
- * The function start_scan should initiate the background
- * scanning and can't sleep.
- */
- void (*scan_syncro)(struct net_device *dev);
- void (*start_scan)(struct net_device *dev);
- void (*stop_scan)(struct net_device *dev);
-
- /* indicate the driver that the link state is changed
- * for example it may indicate the card is associated now.
- * Driver might be interested in this to apply RX filter
- * rules or simply light the LINK led
- */
- void (*link_change)(struct net_device *dev);
-
- /* these two function indicates to the HW when to start
- * and stop to send beacons. This is used when the
- * IEEE_SOFTMAC_BEACONS is not set. For now the
- * stop_send_bacons is NOT guaranteed to be called only
- * after start_send_beacons.
- */
- void (*start_send_beacons) (struct net_device *dev);
- void (*stop_send_beacons) (struct net_device *dev);
-
- /* power save mode related */
- void (*sta_wake_up) (struct net_device *dev);
- void (*ps_request_tx_ack) (struct net_device *dev);
- void (*enter_sleep_state) (struct net_device *dev, u32 th, u32 tl);
- short (*ps_is_queue_empty) (struct net_device *dev);
-
- /* QoS related */
- //void (*wmm_param_update) (struct net_device *dev, u8 *ac_param);
- //void (*wmm_param_update) (struct ieee80211_device *ieee);
-
- /* This must be the last item so that it points to the data
- * allocated beyond this structure by alloc_ieee80211 */
- u8 priv[0];
-};
-
-#define IEEE_A (1<<0)
-#define IEEE_B (1<<1)
-#define IEEE_G (1<<2)
-#define IEEE_MODE_MASK (IEEE_A|IEEE_B|IEEE_G)
-
-/* Generate a 802.11 header */
-
-/* Uses the channel change callback directly
- * instead of [start/stop] scan callbacks
- */
-#define IEEE_SOFTMAC_SCAN (1<<2)
-
-/* Perform authentication and association handshake */
-#define IEEE_SOFTMAC_ASSOCIATE (1<<3)
-
-/* Generate probe requests */
-#define IEEE_SOFTMAC_PROBERQ (1<<4)
-
-/* Generate response to probe requests */
-#define IEEE_SOFTMAC_PROBERS (1<<5)
-
-/* The ieee802.11 stack will manages the netif queue
- * wake/stop for the driver, taking care of 802.11
- * fragmentation. See softmac.c for details. */
-#define IEEE_SOFTMAC_TX_QUEUE (1<<7)
-
-/* Uses only the softmac_data_hard_start_xmit
- * even for TX management frames.
- */
-#define IEEE_SOFTMAC_SINGLE_QUEUE (1<<8)
-
-/* Generate beacons. The stack will enqueue beacons
- * to the card
- */
-#define IEEE_SOFTMAC_BEACONS (1<<6)
-
-
-
-static inline void *ieee80211_priv(struct net_device *dev)
-{
- return ((struct ieee80211_device *)netdev_priv(dev))->priv;
-}
-
-static inline int ieee80211_is_empty_essid(const char *essid, int essid_len)
-{
- /* Single white space is for Linksys APs */
- if (essid_len == 1 && essid[0] == ' ')
- return 1;
-
- /* Otherwise, if the entire essid is 0, we assume it is hidden */
- while (essid_len) {
- essid_len--;
- if (essid[essid_len] != '\0')
- return 0;
- }
-
- return 1;
-}
-
-static inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee,
- int mode)
-{
- /*
- * It is possible for both access points and our device to support
- * combinations of modes, so as long as there is one valid combination
- * of ap/device supported modes, then return success
- *
- */
- if ((mode & IEEE_A) &&
- (ieee->modulation & IEEE80211_OFDM_MODULATION) &&
- (ieee->freq_band & IEEE80211_52GHZ_BAND))
- return 1;
-
- if ((mode & IEEE_G) &&
- (ieee->modulation & IEEE80211_OFDM_MODULATION) &&
- (ieee->freq_band & IEEE80211_24GHZ_BAND))
- return 1;
-
- if ((mode & IEEE_B) &&
- (ieee->modulation & IEEE80211_CCK_MODULATION) &&
- (ieee->freq_band & IEEE80211_24GHZ_BAND))
- return 1;
-
- return 0;
-}
-
-static inline int ieee80211_get_hdrlen(u16 fc)
-{
- int hdrlen = 24;
-
- switch (WLAN_FC_GET_TYPE(fc)) {
- case IEEE80211_FTYPE_DATA:
- if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS))
- hdrlen = 30; /* Addr4 */
- if(IEEE80211_QOS_HAS_SEQ(fc))
- hdrlen += 2; /* QOS ctrl*/
- break;
- case IEEE80211_FTYPE_CTL:
- switch (WLAN_FC_GET_STYPE(fc)) {
- case IEEE80211_STYPE_CTS:
- case IEEE80211_STYPE_ACK:
- hdrlen = 10;
- break;
- default:
- hdrlen = 16;
- break;
- }
- break;
- }
-
- return hdrlen;
-}
-
-
-
-/* ieee80211.c */
-extern void free_ieee80211(struct net_device *dev);
-extern struct net_device *alloc_ieee80211(int sizeof_priv);
-
-extern int ieee80211_set_encryption(struct ieee80211_device *ieee);
-
-/* ieee80211_tx.c */
-
-extern int ieee80211_encrypt_fragment(struct ieee80211_device *ieee,
- struct sk_buff *frag, int hdr_len);
-
-extern int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev);
-extern void ieee80211_txb_free(struct ieee80211_txb *);
-
-
-/* ieee80211_rx.c */
-extern int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
- struct ieee80211_rx_stats *rx_stats);
-extern void ieee80211_rx_mgt(struct ieee80211_device *ieee,
- struct ieee80211_hdr_4addr *header,
- struct ieee80211_rx_stats *stats);
-
-/* ieee80211_wx.c */
-extern int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *key);
-extern int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *key);
-extern int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *key);
-extern int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
-int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- struct iw_param *data, char *extra);
-int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
-
-int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len);
-/* ieee80211_softmac.c */
-extern short ieee80211_is_54g(const struct ieee80211_network *net);
-extern short ieee80211_is_shortslot(const struct ieee80211_network *net);
-extern int ieee80211_rx_frame_softmac(struct ieee80211_device *ieee,
- struct sk_buff *skb,
- struct ieee80211_rx_stats *rx_stats,
- u16 type, u16 stype);
-extern void ieee80211_softmac_new_net(struct ieee80211_device *ieee,
- struct ieee80211_network *net);
-
-extern void ieee80211_softmac_xmit(struct ieee80211_txb *txb,
- struct ieee80211_device *ieee);
-extern void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee);
-extern void ieee80211_start_bss(struct ieee80211_device *ieee);
-extern void ieee80211_start_master_bss(struct ieee80211_device *ieee);
-extern void ieee80211_start_ibss(struct ieee80211_device *ieee);
-extern void ieee80211_softmac_init(struct ieee80211_device *ieee);
-extern void ieee80211_softmac_free(struct ieee80211_device *ieee);
-extern void ieee80211_associate_abort(struct ieee80211_device *ieee);
-extern void ieee80211_disassociate(struct ieee80211_device *ieee);
-extern void ieee80211_stop_scan(struct ieee80211_device *ieee);
-extern void ieee80211_start_scan_syncro(struct ieee80211_device *ieee);
-extern void ieee80211_check_all_nets(struct ieee80211_device *ieee);
-extern void ieee80211_start_protocol(struct ieee80211_device *ieee);
-extern void ieee80211_stop_protocol(struct ieee80211_device *ieee);
-extern void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee);
-extern void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee);
-extern void ieee80211_reset_queue(struct ieee80211_device *ieee);
-extern void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee);
-extern void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee);
-extern struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee);
-extern void ieee80211_start_send_beacons(struct ieee80211_device *ieee);
-extern void ieee80211_stop_send_beacons(struct ieee80211_device *ieee);
-extern int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee,
- struct iw_point *p);
-extern void notify_wx_assoc_event(struct ieee80211_device *ieee);
-extern void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success);
-extern void SendDisassociation(struct ieee80211_device *ieee, u8 *asSta,
- u8 asRsn);
-extern void ieee80211_rtl_start_scan(struct ieee80211_device *ieee);
-
-//Add for RF power on power off by lizhaoming 080512
-extern void SendDisassociation(struct ieee80211_device *ieee, u8 *asSta,
- u8 asRsn);
-
-/* ieee80211_crypt_ccmp&tkip&wep.c */
-extern void ieee80211_tkip_null(void);
-extern void ieee80211_wep_null(void);
-extern void ieee80211_ccmp_null(void);
-/* ieee80211_softmac_wx.c */
-
-extern int ieee80211_wx_get_wap(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *ext);
-
-extern int ieee80211_wx_set_wap(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *awrq,
- char *extra);
-
-extern int ieee80211_wx_get_essid(struct ieee80211_device *ieee,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *b);
-
-extern int ieee80211_wx_set_rate(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
-
-extern int ieee80211_wx_get_rate(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
-
-extern int ieee80211_wx_set_mode(struct ieee80211_device *ieee,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *b);
-
-extern int ieee80211_wx_set_scan(struct ieee80211_device *ieee,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *b);
-
-extern int ieee80211_wx_set_essid(struct ieee80211_device *ieee,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra);
-
-extern int ieee80211_wx_get_mode(struct ieee80211_device *ieee,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *b);
-
-extern int ieee80211_wx_set_freq(struct ieee80211_device *ieee,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *b);
-
-extern int ieee80211_wx_get_freq(struct ieee80211_device *ieee,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *b);
-
-extern void ieee80211_wx_sync_scan_wq(struct work_struct *work);
-
-extern int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
-
-extern int ieee80211_wx_get_name(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
-
-extern int ieee80211_wx_set_power(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
-
-extern int ieee80211_wx_get_power(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
-
-extern void ieee80211_softmac_ips_scan_syncro(struct ieee80211_device *ieee);
-
-extern void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee,
- short pwr);
-
-extern const long ieee80211_wlan_frequencies[];
-
-extern inline void ieee80211_increment_scans(struct ieee80211_device *ieee)
-{
- ieee->scans++;
-}
-
-extern inline int ieee80211_get_scans(struct ieee80211_device *ieee)
-{
- return ieee->scans;
-}
-
-static inline const char *escape_essid(const char *essid, u8 essid_len) {
- static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
- const char *s = essid;
- char *d = escaped;
-
- if (ieee80211_is_empty_essid(essid, essid_len)) {
- memcpy(escaped, "<hidden>", sizeof("<hidden>"));
- return escaped;
- }
-
- essid_len = min(essid_len, (u8)IW_ESSID_MAX_SIZE);
- while (essid_len--) {
- if (*s == '\0') {
- *d++ = '\\';
- *d++ = '0';
- s++;
- } else {
- *d++ = *s++;
- }
- }
- *d = '\0';
- return escaped;
-}
-#endif /* IEEE80211_H */
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c
deleted file mode 100644
index 101f0c0cdb0a..000000000000
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Host AP crypto routines
- *
- * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
- * Portions Copyright (C) 2004, Intel Corporation <jketreno@linux.intel.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation. See README and COPYING for
- * more details.
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-//#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-
-#include "ieee80211.h"
-
-MODULE_AUTHOR("Jouni Malinen");
-MODULE_DESCRIPTION("HostAP crypto");
-MODULE_LICENSE("GPL");
-
-struct ieee80211_crypto_alg {
- struct list_head list;
- struct ieee80211_crypto_ops *ops;
-};
-
-
-struct ieee80211_crypto {
- struct list_head algs;
- spinlock_t lock;
-};
-
-static struct ieee80211_crypto *hcrypt;
-
-void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force)
-{
- struct list_head *ptr, *n;
- struct ieee80211_crypt_data *entry;
-
- for (ptr = ieee->crypt_deinit_list.next, n = ptr->next;
- ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) {
- entry = list_entry(ptr, struct ieee80211_crypt_data, list);
-
- if (atomic_read(&entry->refcnt) != 0 && !force)
- continue;
-
- list_del(ptr);
-
- if (entry->ops)
- entry->ops->deinit(entry->priv);
- kfree(entry);
- }
-}
-
-void ieee80211_crypt_deinit_handler(unsigned long data)
-{
- struct ieee80211_device *ieee = (struct ieee80211_device *)data;
- unsigned long flags;
-
- spin_lock_irqsave(&ieee->lock, flags);
- ieee80211_crypt_deinit_entries(ieee, 0);
- if (!list_empty(&ieee->crypt_deinit_list)) {
- pr_debug("entries remaining in delayed crypt deletion list\n");
- ieee->crypt_deinit_timer.expires = jiffies + HZ;
- add_timer(&ieee->crypt_deinit_timer);
- }
- spin_unlock_irqrestore(&ieee->lock, flags);
-
-}
-
-void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
- struct ieee80211_crypt_data **crypt)
-{
- struct ieee80211_crypt_data *tmp;
- unsigned long flags;
-
- if (*crypt == NULL)
- return;
-
- tmp = *crypt;
- *crypt = NULL;
-
- /* must not run ops->deinit() while there may be pending encrypt or
- * decrypt operations. Use a list of delayed deinits to avoid needing
- * locking. */
-
- spin_lock_irqsave(&ieee->lock, flags);
- list_add(&tmp->list, &ieee->crypt_deinit_list);
- if (!timer_pending(&ieee->crypt_deinit_timer)) {
- ieee->crypt_deinit_timer.expires = jiffies + HZ;
- add_timer(&ieee->crypt_deinit_timer);
- }
- spin_unlock_irqrestore(&ieee->lock, flags);
-}
-
-int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops)
-{
- unsigned long flags;
- struct ieee80211_crypto_alg *alg;
-
- if (hcrypt == NULL)
- return -1;
-
- alg = kzalloc(sizeof(*alg), GFP_KERNEL);
- if (alg == NULL)
- return -ENOMEM;
-
- alg->ops = ops;
-
- spin_lock_irqsave(&hcrypt->lock, flags);
- list_add(&alg->list, &hcrypt->algs);
- spin_unlock_irqrestore(&hcrypt->lock, flags);
-
- pr_debug("registered algorithm '%s'\n", ops->name);
-
- return 0;
-}
-
-int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops)
-{
- unsigned long flags;
- struct list_head *ptr;
- struct ieee80211_crypto_alg *del_alg = NULL;
-
- if (hcrypt == NULL)
- return -1;
-
- spin_lock_irqsave(&hcrypt->lock, flags);
- for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) {
- struct ieee80211_crypto_alg *alg =
- (struct ieee80211_crypto_alg *) ptr;
- if (alg->ops == ops) {
- list_del(&alg->list);
- del_alg = alg;
- break;
- }
- }
- spin_unlock_irqrestore(&hcrypt->lock, flags);
-
- if (del_alg) {
- pr_debug("unregistered algorithm '%s'\n", ops->name);
- kfree(del_alg);
- }
-
- return del_alg ? 0 : -1;
-}
-
-
-struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name)
-{
- unsigned long flags;
- struct list_head *ptr;
- struct ieee80211_crypto_alg *found_alg = NULL;
-
- if (hcrypt == NULL)
- return NULL;
-
- spin_lock_irqsave(&hcrypt->lock, flags);
- for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) {
- struct ieee80211_crypto_alg *alg =
- (struct ieee80211_crypto_alg *) ptr;
- if (strcmp(alg->ops->name, name) == 0) {
- found_alg = alg;
- break;
- }
- }
- spin_unlock_irqrestore(&hcrypt->lock, flags);
-
- if (found_alg)
- return found_alg->ops;
- else
- return NULL;
-}
-
-
-static void *ieee80211_crypt_null_init(int keyidx) { return (void *) 1; }
-static void ieee80211_crypt_null_deinit(void *priv) {}
-
-static struct ieee80211_crypto_ops ieee80211_crypt_null = {
- .name = "NULL",
- .init = ieee80211_crypt_null_init,
- .deinit = ieee80211_crypt_null_deinit,
- .encrypt_mpdu = NULL,
- .decrypt_mpdu = NULL,
- .encrypt_msdu = NULL,
- .decrypt_msdu = NULL,
- .set_key = NULL,
- .get_key = NULL,
- .extra_prefix_len = 0,
- .extra_postfix_len = 0,
- .owner = THIS_MODULE,
-};
-
-
-int ieee80211_crypto_init(void)
-{
- int ret = -ENOMEM;
-
- hcrypt = kzalloc(sizeof(*hcrypt), GFP_KERNEL);
- if (!hcrypt)
- goto out;
-
- INIT_LIST_HEAD(&hcrypt->algs);
- spin_lock_init(&hcrypt->lock);
-
- ret = ieee80211_register_crypto_ops(&ieee80211_crypt_null);
- if (ret < 0) {
- kfree(hcrypt);
- hcrypt = NULL;
- }
-out:
- return ret;
-}
-
-
-void ieee80211_crypto_deinit(void)
-{
- struct list_head *ptr, *n;
- struct ieee80211_crypto_alg *alg = NULL;
-
- if (hcrypt == NULL)
- return;
-
- list_for_each_safe(ptr, n, &hcrypt->algs) {
- alg = list_entry(ptr, struct ieee80211_crypto_alg, list);
- if (alg) {
- list_del(ptr);
- pr_debug("unregistered algorithm '%s' (deinit)\n",
- alg->ops->name);
- kfree(alg);
- }
- }
- kfree(hcrypt);
-}
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.h b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.h
deleted file mode 100644
index 0b4ea431982d..000000000000
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Original code based on Host AP (software wireless LAN access point) driver
- * for Intersil Prism2/2.5/3.
- *
- * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
- * <jkmaline@cc.hut.fi>
- * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
- *
- * Adaption to a generic IEEE 802.11 stack by James Ketrenos
- * <jketreno@linux.intel.com>
- *
- * Copyright (c) 2004, Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation. See README and COPYING for
- * more details.
- */
-
-/*
- * This file defines the interface to the ieee80211 crypto module.
- */
-#ifndef IEEE80211_CRYPT_H
-#define IEEE80211_CRYPT_H
-
-#include <linux/skbuff.h>
-
-struct ieee80211_crypto_ops {
- const char *name;
-
- /* init new crypto context (e.g., allocate private data space,
- * select IV, etc.); returns NULL on failure or pointer to allocated
- * private data on success */
- void * (*init)(int keyidx);
-
- /* deinitialize crypto context and free allocated private data */
- void (*deinit)(void *priv);
-
- /* encrypt/decrypt return < 0 on error or >= 0 on success. The return
- * value from decrypt_mpdu is passed as the keyidx value for
- * decrypt_msdu. skb must have enough head and tail room for the
- * encryption; if not, error will be returned; these functions are
- * called for all MPDUs (i.e., fragments).
- */
- int (*encrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
- int (*decrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
-
- /* These functions are called for full MSDUs, i.e. full frames.
- * These can be NULL if full MSDU operations are not needed. */
- int (*encrypt_msdu)(struct sk_buff *skb, int hdr_len, void *priv);
- int (*decrypt_msdu)(struct sk_buff *skb, int keyidx, int hdr_len,
- void *priv);
-
- int (*set_key)(void *key, int len, u8 *seq, void *priv);
- int (*get_key)(void *key, int len, u8 *seq, void *priv);
-
- /* procfs handler for printing out key information and possible
- * statistics */
- char * (*print_stats)(char *p, void *priv);
-
- /* maximum number of bytes added by encryption; encrypt buf is
- * allocated with extra_prefix_len bytes, copy of in_buf, and
- * extra_postfix_len; encrypt need not use all this space, but
- * the result must start at the beginning of the buffer and correct
- * length must be returned */
- int extra_prefix_len, extra_postfix_len;
-
- struct module *owner;
-};
-
-struct ieee80211_crypt_data {
- struct list_head list; /* delayed deletion list */
- struct ieee80211_crypto_ops *ops;
- void *priv;
- atomic_t refcnt;
-};
-
-int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops);
-int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops);
-struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name);
-void ieee80211_crypt_deinit_entries(struct ieee80211_device *, int);
-void ieee80211_crypt_deinit_handler(unsigned long);
-void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
- struct ieee80211_crypt_data **crypt);
-
-#endif
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c
deleted file mode 100644
index 4fe253818630..000000000000
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c
+++ /dev/null
@@ -1,455 +0,0 @@
-/*
- * Host AP crypt: host-based CCMP encryption implementation for Host AP driver
- *
- * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation. See README and COPYING for
- * more details.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/if_ether.h>
-#include <linux/if_arp.h>
-#include <linux/string.h>
-#include <linux/wireless.h>
-
-#include "ieee80211.h"
-
-#include <linux/crypto.h>
-#include <linux/scatterlist.h>
-
-MODULE_AUTHOR("Jouni Malinen");
-MODULE_DESCRIPTION("Host AP crypt: CCMP");
-MODULE_LICENSE("GPL");
-
-
-#define AES_BLOCK_LEN 16
-#define CCMP_HDR_LEN 8
-#define CCMP_MIC_LEN 8
-#define CCMP_TK_LEN 16
-#define CCMP_PN_LEN 6
-
-struct ieee80211_ccmp_data {
- u8 key[CCMP_TK_LEN];
- int key_set;
-
- u8 tx_pn[CCMP_PN_LEN];
- u8 rx_pn[CCMP_PN_LEN];
-
- u32 dot11RSNAStatsCCMPFormatErrors;
- u32 dot11RSNAStatsCCMPReplays;
- u32 dot11RSNAStatsCCMPDecryptErrors;
-
- int key_idx;
-
- struct crypto_tfm *tfm;
-
- /* scratch buffers for virt_to_page() (crypto API) */
- u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN],
- tx_e[AES_BLOCK_LEN], tx_s0[AES_BLOCK_LEN];
- u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN];
-};
-
-static void ieee80211_ccmp_aes_encrypt(struct crypto_tfm *tfm,
- const u8 pt[16], u8 ct[16])
-{
- crypto_cipher_encrypt_one((void *)tfm, ct, pt);
-}
-
-static void *ieee80211_ccmp_init(int key_idx)
-{
- struct ieee80211_ccmp_data *priv;
-
- priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
- if (priv == NULL)
- goto fail;
- priv->key_idx = key_idx;
-
- priv->tfm = (void *)crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
- if (IS_ERR(priv->tfm)) {
- pr_debug("could not allocate crypto API aes\n");
- priv->tfm = NULL;
- goto fail;
- }
-
- return priv;
-
-fail:
- if (priv) {
- if (priv->tfm)
- crypto_free_cipher((void *)priv->tfm);
- kfree(priv);
- }
-
- return NULL;
-}
-
-
-static void ieee80211_ccmp_deinit(void *priv)
-{
- struct ieee80211_ccmp_data *_priv = priv;
-
- if (_priv && _priv->tfm)
- crypto_free_cipher((void *)_priv->tfm);
- kfree(priv);
-}
-
-
-static inline void xor_block(u8 *b, u8 *a, size_t len)
-{
- int i;
- for (i = 0; i < len; i++)
- b[i] ^= a[i];
-}
-
-static void ccmp_init_blocks(struct crypto_tfm *tfm,
- struct ieee80211_hdr_4addr *hdr,
- u8 *pn, size_t dlen, u8 *b0, u8 *auth,
- u8 *s0)
-{
- u8 *pos, qc = 0;
- size_t aad_len;
- u16 fc;
- int a4_included, qc_included;
- u8 aad[2 * AES_BLOCK_LEN];
-
- fc = le16_to_cpu(hdr->frame_ctl);
- a4_included = ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
- (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS));
- /*
- qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) &&
- (WLAN_FC_GET_STYPE(fc) & 0x08));
- */
- qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) &&
- (WLAN_FC_GET_STYPE(fc) & 0x80));
- aad_len = 22;
- if (a4_included)
- aad_len += 6;
- if (qc_included) {
- pos = (u8 *) &hdr->addr4;
- if (a4_included)
- pos += 6;
- qc = *pos & 0x0f;
- aad_len += 2;
- }
- /* CCM Initial Block:
- * Flag (Include authentication header, M=3 (8-octet MIC),
- * L=1 (2-octet Dlen))
- * Nonce: 0x00 | A2 | PN
- * Dlen */
- b0[0] = 0x59;
- b0[1] = qc;
- memcpy(b0 + 2, hdr->addr2, ETH_ALEN);
- memcpy(b0 + 8, pn, CCMP_PN_LEN);
- b0[14] = (dlen >> 8) & 0xff;
- b0[15] = dlen & 0xff;
-
- /* AAD:
- * FC with bits 4..6 and 11..13 masked to zero; 14 is always one
- * A1 | A2 | A3
- * SC with bits 4..15 (seq#) masked to zero
- * A4 (if present)
- * QC (if present)
- */
- pos = (u8 *) hdr;
- aad[0] = 0; /* aad_len >> 8 */
- aad[1] = aad_len & 0xff;
- aad[2] = pos[0] & 0x8f;
- aad[3] = pos[1] & 0xc7;
- memcpy(aad + 4, hdr->addr1, 3 * ETH_ALEN);
- pos = (u8 *) &hdr->seq_ctl;
- aad[22] = pos[0] & 0x0f;
- aad[23] = 0; /* all bits masked */
- memset(aad + 24, 0, 8);
- if (a4_included)
- memcpy(aad + 24, hdr->addr4, ETH_ALEN);
- if (qc_included) {
- aad[a4_included ? 30 : 24] = qc;
- /* rest of QC masked */
- }
-
- /* Start with the first block and AAD */
- ieee80211_ccmp_aes_encrypt(tfm, b0, auth);
- xor_block(auth, aad, AES_BLOCK_LEN);
- ieee80211_ccmp_aes_encrypt(tfm, auth, auth);
- xor_block(auth, &aad[AES_BLOCK_LEN], AES_BLOCK_LEN);
- ieee80211_ccmp_aes_encrypt(tfm, auth, auth);
- b0[0] &= 0x07;
- b0[14] = b0[15] = 0;
- ieee80211_ccmp_aes_encrypt(tfm, b0, s0);
-}
-
-static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
-{
- struct ieee80211_ccmp_data *key = priv;
- int data_len, i;
- u8 *pos;
- struct ieee80211_hdr_4addr *hdr;
- int blocks, last, len;
- u8 *mic;
- u8 *b0 = key->tx_b0;
- u8 *b = key->tx_b;
- u8 *e = key->tx_e;
- u8 *s0 = key->tx_s0;
-
- if (skb_headroom(skb) < CCMP_HDR_LEN ||
- skb_tailroom(skb) < CCMP_MIC_LEN ||
- skb->len < hdr_len)
- return -1;
-
- data_len = skb->len - hdr_len;
- pos = skb_push(skb, CCMP_HDR_LEN);
- memmove(pos, pos + CCMP_HDR_LEN, hdr_len);
- pos += hdr_len;
-
- i = CCMP_PN_LEN - 1;
- while (i >= 0) {
- key->tx_pn[i]++;
- if (key->tx_pn[i] != 0)
- break;
- i--;
- }
-
- *pos++ = key->tx_pn[5];
- *pos++ = key->tx_pn[4];
- *pos++ = 0;
- *pos++ = (key->key_idx << 6) | (1 << 5) /* Ext IV included */;
- *pos++ = key->tx_pn[3];
- *pos++ = key->tx_pn[2];
- *pos++ = key->tx_pn[1];
- *pos++ = key->tx_pn[0];
-
- hdr = (struct ieee80211_hdr_4addr *)skb->data;
- mic = skb_put(skb, CCMP_MIC_LEN);
-
- ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0);
-
- blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
- last = data_len % AES_BLOCK_LEN;
-
- for (i = 1; i <= blocks; i++) {
- len = (i == blocks && last) ? last : AES_BLOCK_LEN;
- /* Authentication */
- xor_block(b, pos, len);
- ieee80211_ccmp_aes_encrypt(key->tfm, b, b);
- /* Encryption, with counter */
- b0[14] = (i >> 8) & 0xff;
- b0[15] = i & 0xff;
- ieee80211_ccmp_aes_encrypt(key->tfm, b0, e);
- xor_block(pos, e, len);
- pos += len;
- }
-
- for (i = 0; i < CCMP_MIC_LEN; i++)
- mic[i] = b[i] ^ s0[i];
-
- return 0;
-}
-
-
-static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
-{
- struct ieee80211_ccmp_data *key = priv;
- u8 keyidx, *pos;
- struct ieee80211_hdr_4addr *hdr;
- u8 pn[6];
- size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN - CCMP_MIC_LEN;
- u8 *mic = skb->data + skb->len - CCMP_MIC_LEN;
- u8 *b0 = key->rx_b0;
- u8 *b = key->rx_b;
- u8 *a = key->rx_a;
- int i, blocks, last, len;
-
- if (skb->len < hdr_len + CCMP_HDR_LEN + CCMP_MIC_LEN) {
- key->dot11RSNAStatsCCMPFormatErrors++;
- return -1;
- }
-
- hdr = (struct ieee80211_hdr_4addr *)skb->data;
- pos = skb->data + hdr_len;
- keyidx = pos[3];
- if (!(keyidx & (1 << 5))) {
- if (net_ratelimit()) {
- pr_debug("received packet without ExtIV flag from %pM\n",
- hdr->addr2);
- }
- key->dot11RSNAStatsCCMPFormatErrors++;
- return -2;
- }
- keyidx >>= 6;
- if (key->key_idx != keyidx) {
- pr_debug("RX tkey->key_idx=%d frame keyidx=%d priv=%p\n",
- key->key_idx, keyidx, priv);
- return -6;
- }
- if (!key->key_set) {
- if (net_ratelimit()) {
- pr_debug("received packet from %pM with keyid=%d that does not have a configured key\n",
- hdr->addr2, keyidx);
- }
- return -3;
- }
-
- pn[0] = pos[7];
- pn[1] = pos[6];
- pn[2] = pos[5];
- pn[3] = pos[4];
- pn[4] = pos[1];
- pn[5] = pos[0];
- pos += 8;
-
- if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) {
- if (net_ratelimit()) {
- pr_debug("replay detected: STA=%pM previous PN %pm received PN %pm\n",
- hdr->addr2, key->rx_pn, pn);
- }
- key->dot11RSNAStatsCCMPReplays++;
- return -4;
- }
-
- ccmp_init_blocks(key->tfm, hdr, pn, data_len, b0, a, b);
- xor_block(mic, b, CCMP_MIC_LEN);
-
- blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
- last = data_len % AES_BLOCK_LEN;
-
- for (i = 1; i <= blocks; i++) {
- len = (i == blocks && last) ? last : AES_BLOCK_LEN;
- /* Decrypt, with counter */
- b0[14] = (i >> 8) & 0xff;
- b0[15] = i & 0xff;
- ieee80211_ccmp_aes_encrypt(key->tfm, b0, b);
- xor_block(pos, b, len);
- /* Authentication */
- xor_block(a, pos, len);
- ieee80211_ccmp_aes_encrypt(key->tfm, a, a);
- pos += len;
- }
-
- if (memcmp(mic, a, CCMP_MIC_LEN) != 0) {
- if (net_ratelimit())
- pr_debug("decrypt failed: STA=%pM\n", hdr->addr2);
-
- key->dot11RSNAStatsCCMPDecryptErrors++;
- return -5;
- }
-
- memcpy(key->rx_pn, pn, CCMP_PN_LEN);
-
- /* Remove hdr and MIC */
- memmove(skb->data + CCMP_HDR_LEN, skb->data, hdr_len);
- skb_pull(skb, CCMP_HDR_LEN);
- skb_trim(skb, skb->len - CCMP_MIC_LEN);
-
- return keyidx;
-}
-
-
-static int ieee80211_ccmp_set_key(void *key, int len, u8 *seq, void *priv)
-{
- struct ieee80211_ccmp_data *data = priv;
- int keyidx;
- struct crypto_tfm *tfm = data->tfm;
-
- keyidx = data->key_idx;
- memset(data, 0, sizeof(*data));
- data->key_idx = keyidx;
- data->tfm = tfm;
- if (len == CCMP_TK_LEN) {
- memcpy(data->key, key, CCMP_TK_LEN);
- data->key_set = 1;
- if (seq) {
- data->rx_pn[0] = seq[5];
- data->rx_pn[1] = seq[4];
- data->rx_pn[2] = seq[3];
- data->rx_pn[3] = seq[2];
- data->rx_pn[4] = seq[1];
- data->rx_pn[5] = seq[0];
- }
- crypto_cipher_setkey((void *)data->tfm, data->key, CCMP_TK_LEN);
- } else if (len == 0)
- data->key_set = 0;
- else
- return -1;
-
- return 0;
-}
-
-
-static int ieee80211_ccmp_get_key(void *key, int len, u8 *seq, void *priv)
-{
- struct ieee80211_ccmp_data *data = priv;
-
- if (len < CCMP_TK_LEN)
- return -1;
-
- if (!data->key_set)
- return 0;
- memcpy(key, data->key, CCMP_TK_LEN);
-
- if (seq) {
- seq[0] = data->tx_pn[5];
- seq[1] = data->tx_pn[4];
- seq[2] = data->tx_pn[3];
- seq[3] = data->tx_pn[2];
- seq[4] = data->tx_pn[1];
- seq[5] = data->tx_pn[0];
- }
-
- return CCMP_TK_LEN;
-}
-
-
-static char *ieee80211_ccmp_print_stats(char *p, void *priv)
-{
- struct ieee80211_ccmp_data *ccmp = priv;
- p += sprintf(p,
- "key[%d] alg=CCMP key_set=%d tx_pn=%pm rx_pn=%pm format_errors=%d replays=%d decrypt_errors=%d\n",
- ccmp->key_idx, ccmp->key_set,
- ccmp->tx_pn, ccmp->rx_pn,
- ccmp->dot11RSNAStatsCCMPFormatErrors,
- ccmp->dot11RSNAStatsCCMPReplays,
- ccmp->dot11RSNAStatsCCMPDecryptErrors);
-
- return p;
-}
-
-void ieee80211_ccmp_null(void)
-{
- return;
-}
-static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = {
- .name = "CCMP",
- .init = ieee80211_ccmp_init,
- .deinit = ieee80211_ccmp_deinit,
- .encrypt_mpdu = ieee80211_ccmp_encrypt,
- .decrypt_mpdu = ieee80211_ccmp_decrypt,
- .encrypt_msdu = NULL,
- .decrypt_msdu = NULL,
- .set_key = ieee80211_ccmp_set_key,
- .get_key = ieee80211_ccmp_get_key,
- .print_stats = ieee80211_ccmp_print_stats,
- .extra_prefix_len = CCMP_HDR_LEN,
- .extra_postfix_len = CCMP_MIC_LEN,
- .owner = THIS_MODULE,
-};
-
-
-int ieee80211_crypto_ccmp_init(void)
-{
- return ieee80211_register_crypto_ops(&ieee80211_crypt_ccmp);
-}
-
-
-void ieee80211_crypto_ccmp_exit(void)
-{
- ieee80211_unregister_crypto_ops(&ieee80211_crypt_ccmp);
-}
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c
deleted file mode 100644
index 6c1acc5dfba7..000000000000
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c
+++ /dev/null
@@ -1,740 +0,0 @@
-/*
- * Host AP crypt: host-based TKIP encryption implementation for Host AP driver
- *
- * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation. See README and COPYING for
- * more details.
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/if_ether.h>
-#include <linux/if_arp.h>
-#include <asm/string.h>
-
-#include "ieee80211.h"
-
-#include <linux/crypto.h>
-#include <linux/scatterlist.h>
-#include <linux/crc32.h>
-
-MODULE_AUTHOR("Jouni Malinen");
-MODULE_DESCRIPTION("Host AP crypt: TKIP");
-MODULE_LICENSE("GPL");
-
-
-struct ieee80211_tkip_data {
-#define TKIP_KEY_LEN 32
- u8 key[TKIP_KEY_LEN];
- int key_set;
-
- u32 tx_iv32;
- u16 tx_iv16;
- u16 tx_ttak[5];
- int tx_phase1_done;
-
- u32 rx_iv32;
- u16 rx_iv16;
- u16 rx_ttak[5];
- int rx_phase1_done;
- u32 rx_iv32_new;
- u16 rx_iv16_new;
-
- u32 dot11RSNAStatsTKIPReplays;
- u32 dot11RSNAStatsTKIPICVErrors;
- u32 dot11RSNAStatsTKIPLocalMICFailures;
-
- int key_idx;
-
- struct crypto_blkcipher *rx_tfm_arc4;
- struct crypto_hash *rx_tfm_michael;
- struct crypto_blkcipher *tx_tfm_arc4;
- struct crypto_hash *tx_tfm_michael;
- struct crypto_tfm *tfm_arc4;
- struct crypto_tfm *tfm_michael;
-
- /* scratch buffers for virt_to_page() (crypto API) */
- u8 rx_hdr[16], tx_hdr[16];
-};
-
-static void *ieee80211_tkip_init(int key_idx)
-{
- struct ieee80211_tkip_data *priv;
-
- priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
- if (priv == NULL)
- goto fail;
- priv->key_idx = key_idx;
-
- priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
- CRYPTO_ALG_ASYNC);
- if (IS_ERR(priv->tx_tfm_arc4)) {
- printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
- "crypto API arc4\n");
- priv->tx_tfm_arc4 = NULL;
- goto fail;
- }
-
- priv->tx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
- CRYPTO_ALG_ASYNC);
- if (IS_ERR(priv->tx_tfm_michael)) {
- printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
- "crypto API michael_mic\n");
- priv->tx_tfm_michael = NULL;
- goto fail;
- }
-
- priv->rx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
- CRYPTO_ALG_ASYNC);
- if (IS_ERR(priv->rx_tfm_arc4)) {
- printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
- "crypto API arc4\n");
- priv->rx_tfm_arc4 = NULL;
- goto fail;
- }
-
- priv->rx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
- CRYPTO_ALG_ASYNC);
- if (IS_ERR(priv->rx_tfm_michael)) {
- printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
- "crypto API michael_mic\n");
- priv->rx_tfm_michael = NULL;
- goto fail;
- }
-
- return priv;
-
-fail:
- if (priv) {
- if (priv->tx_tfm_michael)
- crypto_free_hash(priv->tx_tfm_michael);
- if (priv->tx_tfm_arc4)
- crypto_free_blkcipher(priv->tx_tfm_arc4);
- if (priv->rx_tfm_michael)
- crypto_free_hash(priv->rx_tfm_michael);
- if (priv->rx_tfm_arc4)
- crypto_free_blkcipher(priv->rx_tfm_arc4);
- kfree(priv);
- }
-
- return NULL;
-}
-
-
-static void ieee80211_tkip_deinit(void *priv)
-{
- struct ieee80211_tkip_data *_priv = priv;
-
- if (_priv) {
- if (_priv->tx_tfm_michael)
- crypto_free_hash(_priv->tx_tfm_michael);
- if (_priv->tx_tfm_arc4)
- crypto_free_blkcipher(_priv->tx_tfm_arc4);
- if (_priv->rx_tfm_michael)
- crypto_free_hash(_priv->rx_tfm_michael);
- if (_priv->rx_tfm_arc4)
- crypto_free_blkcipher(_priv->rx_tfm_arc4);
- }
- kfree(priv);
-}
-
-
-static inline u16 RotR1(u16 val)
-{
- return (val >> 1) | (val << 15);
-}
-
-
-static inline u8 Lo8(u16 val)
-{
- return val & 0xff;
-}
-
-
-static inline u8 Hi8(u16 val)
-{
- return val >> 8;
-}
-
-
-static inline u16 Lo16(u32 val)
-{
- return val & 0xffff;
-}
-
-
-static inline u16 Hi16(u32 val)
-{
- return val >> 16;
-}
-
-
-static inline u16 Mk16(u8 hi, u8 lo)
-{
- return lo | (((u16) hi) << 8);
-}
-
-
-static inline u16 Mk16_le(u16 *v)
-{
- return le16_to_cpu(*v);
-}
-
-
-static const u16 Sbox[256] = {
- 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
- 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
- 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
- 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
- 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
- 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
- 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
- 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
- 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
- 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
- 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
- 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
- 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
- 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
- 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
- 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
- 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
- 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
- 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
- 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
- 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
- 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
- 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
- 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
- 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
- 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
- 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
- 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
- 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
- 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
- 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
- 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
-};
-
-
-static inline u16 _S_(u16 v)
-{
- u16 t = Sbox[Hi8(v)];
- return Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8));
-}
-
-#define PHASE1_LOOP_COUNT 8
-
-static void tkip_mixing_phase1(u16 *TTAK, const u8 *TK, const u8 *TA, u32 IV32)
-{
- int i, j;
-
- /* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */
- TTAK[0] = Lo16(IV32);
- TTAK[1] = Hi16(IV32);
- TTAK[2] = Mk16(TA[1], TA[0]);
- TTAK[3] = Mk16(TA[3], TA[2]);
- TTAK[4] = Mk16(TA[5], TA[4]);
-
- for (i = 0; i < PHASE1_LOOP_COUNT; i++) {
- j = 2 * (i & 1);
- TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j]));
- TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j]));
- TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j]));
- TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j]));
- TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i;
- }
-}
-
-
-static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK,
- u16 IV16)
-{
- /* Make temporary area overlap WEP seed so that the final copy can be
- * avoided on little endian hosts. */
- u16 *PPK = (u16 *) &WEPSeed[4];
-
- /* Step 1 - make copy of TTAK and bring in TSC */
- PPK[0] = TTAK[0];
- PPK[1] = TTAK[1];
- PPK[2] = TTAK[2];
- PPK[3] = TTAK[3];
- PPK[4] = TTAK[4];
- PPK[5] = TTAK[4] + IV16;
-
- /* Step 2 - 96-bit bijective mixing using S-box */
- PPK[0] += _S_(PPK[5] ^ Mk16_le((u16 *) &TK[0]));
- PPK[1] += _S_(PPK[0] ^ Mk16_le((u16 *) &TK[2]));
- PPK[2] += _S_(PPK[1] ^ Mk16_le((u16 *) &TK[4]));
- PPK[3] += _S_(PPK[2] ^ Mk16_le((u16 *) &TK[6]));
- PPK[4] += _S_(PPK[3] ^ Mk16_le((u16 *) &TK[8]));
- PPK[5] += _S_(PPK[4] ^ Mk16_le((u16 *) &TK[10]));
-
- PPK[0] += RotR1(PPK[5] ^ Mk16_le((u16 *) &TK[12]));
- PPK[1] += RotR1(PPK[0] ^ Mk16_le((u16 *) &TK[14]));
- PPK[2] += RotR1(PPK[1]);
- PPK[3] += RotR1(PPK[2]);
- PPK[4] += RotR1(PPK[3]);
- PPK[5] += RotR1(PPK[4]);
-
- /* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value
- * WEPSeed[0..2] is transmitted as WEP IV */
- WEPSeed[0] = Hi8(IV16);
- WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F;
- WEPSeed[2] = Lo8(IV16);
- WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((u16 *) &TK[0])) >> 1);
-
-#ifdef __BIG_ENDIAN
- {
- int i;
- for (i = 0; i < 6; i++)
- PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8);
- }
-#endif
-}
-
-static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
-{
- struct ieee80211_tkip_data *tkey = priv;
- struct blkcipher_desc desc = {.tfm = tkey->tx_tfm_arc4};
- int len;
- u8 *pos;
- struct ieee80211_hdr_4addr *hdr;
- u8 rc4key[16], *icv;
- u32 crc;
- struct scatterlist sg;
- int ret;
-
- ret = 0;
- if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 ||
- skb->len < hdr_len)
- return -1;
-
- hdr = (struct ieee80211_hdr_4addr *)skb->data;
-
- if (!tkey->tx_phase1_done) {
- tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
- tkey->tx_iv32);
- tkey->tx_phase1_done = 1;
- }
- tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16);
-
- len = skb->len - hdr_len;
- pos = skb_push(skb, 8);
- memmove(pos, pos + 8, hdr_len);
- pos += hdr_len;
-
- *pos++ = rc4key[0];
- *pos++ = rc4key[1];
- *pos++ = rc4key[2];
- *pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */;
- *pos++ = tkey->tx_iv32 & 0xff;
- *pos++ = (tkey->tx_iv32 >> 8) & 0xff;
- *pos++ = (tkey->tx_iv32 >> 16) & 0xff;
- *pos++ = (tkey->tx_iv32 >> 24) & 0xff;
-
- icv = skb_put(skb, 4);
- crc = ~crc32_le(~0, pos, len);
- icv[0] = crc;
- icv[1] = crc >> 8;
- icv[2] = crc >> 16;
- icv[3] = crc >> 24;
- crypto_blkcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16);
- sg_init_one(&sg, pos, len + 4);
- ret = crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
-
- tkey->tx_iv16++;
- if (tkey->tx_iv16 == 0) {
- tkey->tx_phase1_done = 0;
- tkey->tx_iv32++;
- }
- return ret;
-}
-
-static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
-{
- struct ieee80211_tkip_data *tkey = priv;
- struct blkcipher_desc desc = { .tfm = tkey->rx_tfm_arc4 };
- u8 keyidx, *pos;
- u32 iv32;
- u16 iv16;
- struct ieee80211_hdr_4addr *hdr;
- u8 icv[4];
- u32 crc;
- struct scatterlist sg;
- u8 rc4key[16];
- int plen;
-
- if (skb->len < hdr_len + 8 + 4)
- return -1;
-
- hdr = (struct ieee80211_hdr_4addr *)skb->data;
- pos = skb->data + hdr_len;
- keyidx = pos[3];
- if (!(keyidx & (1 << 5))) {
- if (net_ratelimit()) {
- printk(KERN_DEBUG "TKIP: received packet without ExtIV"
- " flag from %pM\n", hdr->addr2);
- }
- return -2;
- }
- keyidx >>= 6;
- if (tkey->key_idx != keyidx) {
- printk(KERN_DEBUG "TKIP: RX tkey->key_idx=%d frame "
- "keyidx=%d priv=%p\n", tkey->key_idx, keyidx, priv);
- return -6;
- }
- if (!tkey->key_set) {
- if (net_ratelimit()) {
- printk(KERN_DEBUG "TKIP: received packet from %pM"
- " with keyid=%d that does not have a configured"
- " key\n", hdr->addr2, keyidx);
- }
- return -3;
- }
- iv16 = (pos[0] << 8) | pos[2];
- iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24);
- pos += 8;
-
- if (iv32 < tkey->rx_iv32 ||
- (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) {
- if (net_ratelimit()) {
- printk(KERN_DEBUG "TKIP: replay detected: STA=%pM"
- " previous TSC %08x%04x received TSC "
- "%08x%04x\n", hdr->addr2,
- tkey->rx_iv32, tkey->rx_iv16, iv32, iv16);
- }
- tkey->dot11RSNAStatsTKIPReplays++;
- return -4;
- }
-
- if (iv32 != tkey->rx_iv32 || !tkey->rx_phase1_done) {
- tkip_mixing_phase1(tkey->rx_ttak, tkey->key, hdr->addr2, iv32);
- tkey->rx_phase1_done = 1;
- }
- tkip_mixing_phase2(rc4key, tkey->key, tkey->rx_ttak, iv16);
-
- plen = skb->len - hdr_len - 12;
- crypto_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16);
- sg_init_one(&sg, pos, plen + 4);
- if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) {
- if (net_ratelimit()) {
- printk(KERN_DEBUG ": TKIP: failed to decrypt "
- "received packet from %pM\n",
- hdr->addr2);
- }
- return -7;
- }
-
- crc = ~crc32_le(~0, pos, plen);
- icv[0] = crc;
- icv[1] = crc >> 8;
- icv[2] = crc >> 16;
- icv[3] = crc >> 24;
- if (memcmp(icv, pos + plen, 4) != 0) {
- if (iv32 != tkey->rx_iv32) {
- /* Previously cached Phase1 result was already lost, so
- * it needs to be recalculated for the next packet. */
- tkey->rx_phase1_done = 0;
- }
- if (net_ratelimit()) {
- printk(KERN_DEBUG "TKIP: ICV error detected: STA="
- "%pM\n", hdr->addr2);
- }
- tkey->dot11RSNAStatsTKIPICVErrors++;
- return -5;
- }
-
- /* Update real counters only after Michael MIC verification has
- * completed */
- tkey->rx_iv32_new = iv32;
- tkey->rx_iv16_new = iv16;
-
- /* Remove IV and ICV */
- memmove(skb->data + 8, skb->data, hdr_len);
- skb_pull(skb, 8);
- skb_trim(skb, skb->len - 4);
-
- return keyidx;
-}
-
-static int michael_mic(struct crypto_hash *tfm_michael, u8 *key, u8 *hdr,
- u8 *data, size_t data_len, u8 *mic)
-{
- struct hash_desc desc;
- struct scatterlist sg[2];
-
- if (tfm_michael == NULL) {
- printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n");
- return -1;
- }
-
- sg_init_table(sg, 2);
- sg_set_buf(&sg[0], hdr, 16);
- sg_set_buf(&sg[1], data, data_len);
-
- if (crypto_hash_setkey(tfm_michael, key, 8))
- return -1;
-
- desc.tfm = tfm_michael;
- desc.flags = 0;
- return crypto_hash_digest(&desc, sg, data_len + 16, mic);
-}
-
-static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr)
-{
- struct ieee80211_hdr_4addr *hdr11;
-
- hdr11 = (struct ieee80211_hdr_4addr *)skb->data;
- switch (le16_to_cpu(hdr11->frame_ctl) &
- (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
- case IEEE80211_FCTL_TODS:
- memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
- memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
- break;
- case IEEE80211_FCTL_FROMDS:
- memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
- memcpy(hdr + ETH_ALEN, hdr11->addr3, ETH_ALEN); /* SA */
- break;
- case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
- memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
- memcpy(hdr + ETH_ALEN, hdr11->addr4, ETH_ALEN); /* SA */
- break;
- case 0:
- memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
- memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
- break;
- }
-
- hdr[12] = 0; /* priority */
-
- hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */
-}
-
-
-static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len,
- void *priv)
-{
- struct ieee80211_tkip_data *tkey = priv;
- u8 *pos;
- struct ieee80211_hdr_4addr *hdr;
-
- hdr = (struct ieee80211_hdr_4addr *)skb->data;
-
- if (skb_tailroom(skb) < 8 || skb->len < hdr_len) {
- printk(KERN_DEBUG "Invalid packet for Michael MIC add "
- "(tailroom=%d hdr_len=%d skb->len=%d)\n",
- skb_tailroom(skb), hdr_len, skb->len);
- return -1;
- }
-
- michael_mic_hdr(skb, tkey->tx_hdr);
-
- if (IEEE80211_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl)))
- tkey->tx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07;
-
- pos = skb_put(skb, 8);
-
- if (michael_mic(tkey->tx_tfm_michael, &tkey->key[16], tkey->tx_hdr,
- skb->data + hdr_len, skb->len - 8 - hdr_len, pos))
- return -1;
-
- return 0;
-}
-
-static void ieee80211_michael_mic_failure(struct net_device *dev,
- struct ieee80211_hdr_4addr *hdr,
- int keyidx)
-{
- union iwreq_data wrqu;
- struct iw_michaelmicfailure ev;
-
- /* TODO: needed parameters: count, keyid, key type, TSC */
- memset(&ev, 0, sizeof(ev));
- ev.flags = keyidx & IW_MICFAILURE_KEY_ID;
- if (hdr->addr1[0] & 0x01)
- ev.flags |= IW_MICFAILURE_GROUP;
- else
- ev.flags |= IW_MICFAILURE_PAIRWISE;
- ev.src_addr.sa_family = ARPHRD_ETHER;
- memcpy(ev.src_addr.sa_data, hdr->addr2, ETH_ALEN);
- memset(&wrqu, 0, sizeof(wrqu));
- wrqu.data.length = sizeof(ev);
- wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *) &ev);
-}
-
-static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
- int hdr_len, void *priv)
-{
- struct ieee80211_tkip_data *tkey = priv;
- u8 mic[8];
- struct ieee80211_hdr_4addr *hdr;
-
- hdr = (struct ieee80211_hdr_4addr *)skb->data;
-
- if (!tkey->key_set)
- return -1;
-
- michael_mic_hdr(skb, tkey->rx_hdr);
- if (IEEE80211_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl)))
- tkey->rx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07;
-
- if (michael_mic(tkey->rx_tfm_michael, &tkey->key[24], tkey->rx_hdr,
- skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
- return -1;
-
- if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
- struct ieee80211_hdr_4addr *hdr;
- hdr = (struct ieee80211_hdr_4addr *)skb->data;
- printk(KERN_DEBUG "%s: Michael MIC verification failed for "
- "MSDU from %pM keyidx=%d\n",
- skb->dev ? skb->dev->name : "N/A", hdr->addr2,
- keyidx);
- if (skb->dev)
- ieee80211_michael_mic_failure(skb->dev, hdr, keyidx);
- tkey->dot11RSNAStatsTKIPLocalMICFailures++;
- return -1;
- }
-
- /* Update TSC counters for RX now that the packet verification has
- * completed. */
- tkey->rx_iv32 = tkey->rx_iv32_new;
- tkey->rx_iv16 = tkey->rx_iv16_new;
-
- skb_trim(skb, skb->len - 8);
-
- return 0;
-}
-
-
-static int ieee80211_tkip_set_key(void *key, int len, u8 *seq, void *priv)
-{
- struct ieee80211_tkip_data *tkey = priv;
- int keyidx;
- struct crypto_hash *tfm = tkey->tx_tfm_michael;
- struct crypto_blkcipher *tfm2 = tkey->tx_tfm_arc4;
- struct crypto_hash *tfm3 = tkey->rx_tfm_michael;
- struct crypto_blkcipher *tfm4 = tkey->rx_tfm_arc4;
-
- keyidx = tkey->key_idx;
- memset(tkey, 0, sizeof(*tkey));
- tkey->key_idx = keyidx;
-
- tkey->tx_tfm_michael = tfm;
- tkey->tx_tfm_arc4 = tfm2;
- tkey->rx_tfm_michael = tfm3;
- tkey->rx_tfm_arc4 = tfm4;
-
- if (len == TKIP_KEY_LEN) {
- memcpy(tkey->key, key, TKIP_KEY_LEN);
- tkey->key_set = 1;
- tkey->tx_iv16 = 1; /* TSC is initialized to 1 */
- if (seq) {
- tkey->rx_iv32 = (seq[5] << 24) | (seq[4] << 16) |
- (seq[3] << 8) | seq[2];
- tkey->rx_iv16 = (seq[1] << 8) | seq[0];
- }
- } else if (len == 0)
- tkey->key_set = 0;
- else
- return -1;
-
- return 0;
-}
-
-
-static int ieee80211_tkip_get_key(void *key, int len, u8 *seq, void *priv)
-{
- struct ieee80211_tkip_data *tkey = priv;
-
- if (len < TKIP_KEY_LEN)
- return -1;
-
- if (!tkey->key_set)
- return 0;
- memcpy(key, tkey->key, TKIP_KEY_LEN);
-
- if (seq) {
- /* Return the sequence number of the last transmitted frame. */
- u16 iv16 = tkey->tx_iv16;
- u32 iv32 = tkey->tx_iv32;
- if (iv16 == 0)
- iv32--;
- iv16--;
- seq[0] = tkey->tx_iv16;
- seq[1] = tkey->tx_iv16 >> 8;
- seq[2] = tkey->tx_iv32;
- seq[3] = tkey->tx_iv32 >> 8;
- seq[4] = tkey->tx_iv32 >> 16;
- seq[5] = tkey->tx_iv32 >> 24;
- }
-
- return TKIP_KEY_LEN;
-}
-
-
-static char *ieee80211_tkip_print_stats(char *p, void *priv)
-{
- struct ieee80211_tkip_data *tkip = priv;
- p += sprintf(p, "key[%d] alg=TKIP key_set=%d "
- "tx_pn=%02x%02x%02x%02x%02x%02x "
- "rx_pn=%02x%02x%02x%02x%02x%02x "
- "replays=%d icv_errors=%d local_mic_failures=%d\n",
- tkip->key_idx, tkip->key_set,
- (tkip->tx_iv32 >> 24) & 0xff,
- (tkip->tx_iv32 >> 16) & 0xff,
- (tkip->tx_iv32 >> 8) & 0xff,
- tkip->tx_iv32 & 0xff,
- (tkip->tx_iv16 >> 8) & 0xff,
- tkip->tx_iv16 & 0xff,
- (tkip->rx_iv32 >> 24) & 0xff,
- (tkip->rx_iv32 >> 16) & 0xff,
- (tkip->rx_iv32 >> 8) & 0xff,
- tkip->rx_iv32 & 0xff,
- (tkip->rx_iv16 >> 8) & 0xff,
- tkip->rx_iv16 & 0xff,
- tkip->dot11RSNAStatsTKIPReplays,
- tkip->dot11RSNAStatsTKIPICVErrors,
- tkip->dot11RSNAStatsTKIPLocalMICFailures);
- return p;
-}
-
-
-static struct ieee80211_crypto_ops ieee80211_crypt_tkip = {
- .name = "TKIP",
- .init = ieee80211_tkip_init,
- .deinit = ieee80211_tkip_deinit,
- .encrypt_mpdu = ieee80211_tkip_encrypt,
- .decrypt_mpdu = ieee80211_tkip_decrypt,
- .encrypt_msdu = ieee80211_michael_mic_add,
- .decrypt_msdu = ieee80211_michael_mic_verify,
- .set_key = ieee80211_tkip_set_key,
- .get_key = ieee80211_tkip_get_key,
- .print_stats = ieee80211_tkip_print_stats,
- .extra_prefix_len = 4 + 4, /* IV + ExtIV */
- .extra_postfix_len = 8 + 4, /* MIC + ICV */
- .owner = THIS_MODULE,
-};
-
-
-int ieee80211_crypto_tkip_init(void)
-{
- return ieee80211_register_crypto_ops(&ieee80211_crypt_tkip);
-}
-
-
-void ieee80211_crypto_tkip_exit(void)
-{
- ieee80211_unregister_crypto_ops(&ieee80211_crypt_tkip);
-}
-
-
-void ieee80211_tkip_null(void)
-{
-}
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_wep.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_wep.c
deleted file mode 100644
index f25367224941..000000000000
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_wep.c
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Host AP crypt: host-based WEP encryption implementation for Host AP driver
- *
- * Copyright (c) 2002-2004, Jouni Malinen <jkmaline@cc.hut.fi>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation. See README and COPYING for
- * more details.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/skbuff.h>
-#include <linux/string.h>
-
-#include "ieee80211.h"
-
-#include <linux/crypto.h>
-#include <linux/scatterlist.h>
-#include <linux/crc32.h>
-
-MODULE_AUTHOR("Jouni Malinen");
-MODULE_DESCRIPTION("Host AP crypt: WEP");
-MODULE_LICENSE("GPL");
-
-struct prism2_wep_data {
- u32 iv;
-#define WEP_KEY_LEN 13
- u8 key[WEP_KEY_LEN + 1];
- u8 key_len;
- u8 key_idx;
- struct crypto_blkcipher *tx_tfm;
- struct crypto_blkcipher *rx_tfm;
-};
-
-static void *prism2_wep_init(int keyidx)
-{
- struct prism2_wep_data *priv;
-
- priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
- if (priv == NULL)
- goto fail;
- priv->key_idx = keyidx;
- priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
- if (IS_ERR(priv->tx_tfm)) {
- pr_debug("could not allocate crypto API arc4\n");
- priv->tx_tfm = NULL;
- goto fail;
- }
- priv->rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
- if (IS_ERR(priv->rx_tfm)) {
- pr_debug("could not allocate crypto API arc4\n");
- priv->rx_tfm = NULL;
- goto fail;
- }
-
- /* start WEP IV from a random value */
- get_random_bytes(&priv->iv, 4);
-
- return priv;
-
-fail:
- if (priv) {
- if (priv->tx_tfm)
- crypto_free_blkcipher(priv->tx_tfm);
- if (priv->rx_tfm)
- crypto_free_blkcipher(priv->rx_tfm);
- kfree(priv);
- }
-
- return NULL;
-}
-
-static void prism2_wep_deinit(void *priv)
-{
- struct prism2_wep_data *_priv = priv;
-
- if (_priv) {
- if (_priv->tx_tfm)
- crypto_free_blkcipher(_priv->tx_tfm);
- if (_priv->rx_tfm)
- crypto_free_blkcipher(_priv->rx_tfm);
- }
-
- kfree(priv);
-}
-
-/* Perform WEP encryption on given skb that has at least 4 bytes of headroom
- * for IV and 4 bytes of tailroom for ICV. Both IV and ICV will be transmitted,
- * so the payload length increases with 8 bytes.
- *
- * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data))
- */
-static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
-{
- struct prism2_wep_data *wep = priv;
- struct blkcipher_desc desc = { .tfm = wep->tx_tfm };
- u32 klen, len;
- u8 key[WEP_KEY_LEN + 3];
- u8 *pos;
- u32 crc;
- u8 *icv;
- struct scatterlist sg;
-
- if (skb_headroom(skb) < 4 || skb_tailroom(skb) < 4 ||
- skb->len < hdr_len)
- return -1;
-
- len = skb->len - hdr_len;
- pos = skb_push(skb, 4);
- memmove(pos, pos + 4, hdr_len);
- pos += hdr_len;
-
- klen = 3 + wep->key_len;
-
- wep->iv++;
-
- /* Fluhrer, Mantin, and Shamir have reported weaknesses in the key
- * scheduling algorithm of RC4. At least IVs (KeyByte + 3, 0xff, N)
- * can be used to speedup attacks, so avoid using them. */
- if ((wep->iv & 0xff00) == 0xff00) {
- u8 B = (wep->iv >> 16) & 0xff;
- if (B >= 3 && B < klen)
- wep->iv += 0x0100;
- }
-
- /* Prepend 24-bit IV to RC4 key and TX frame */
- *pos++ = key[0] = (wep->iv >> 16) & 0xff;
- *pos++ = key[1] = (wep->iv >> 8) & 0xff;
- *pos++ = key[2] = wep->iv & 0xff;
- *pos++ = wep->key_idx << 6;
-
- /* Copy rest of the WEP key (the secret part) */
- memcpy(key + 3, wep->key, wep->key_len);
-
- /* Append little-endian CRC32 and encrypt it to produce ICV */
- crc = ~crc32_le(~0, pos, len);
- icv = skb_put(skb, 4);
- icv[0] = crc;
- icv[1] = crc >> 8;
- icv[2] = crc >> 16;
- icv[3] = crc >> 24;
-
- crypto_blkcipher_setkey(wep->tx_tfm, key, klen);
- sg_init_one(&sg, pos, len + 4);
-
- return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
-}
-
-/* Perform WEP decryption on given buffer. Buffer includes whole WEP part of
- * the frame: IV (4 bytes), encrypted payload (including SNAP header),
- * ICV (4 bytes). len includes both IV and ICV.
- *
- * Returns 0 if frame was decrypted successfully and ICV was correct and -1 on
- * failure. If frame is OK, IV and ICV will be removed.
- */
-static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
-{
- struct prism2_wep_data *wep = priv;
- struct blkcipher_desc desc = { .tfm = wep->rx_tfm };
- u32 klen, plen;
- u8 key[WEP_KEY_LEN + 3];
- u8 keyidx, *pos;
- u32 crc;
- u8 icv[4];
- struct scatterlist sg;
-
- if (skb->len < hdr_len + 8)
- return -1;
-
- pos = skb->data + hdr_len;
- key[0] = *pos++;
- key[1] = *pos++;
- key[2] = *pos++;
- keyidx = *pos++ >> 6;
- if (keyidx != wep->key_idx)
- return -1;
-
- klen = 3 + wep->key_len;
-
- /* Copy rest of the WEP key (the secret part) */
- memcpy(key + 3, wep->key, wep->key_len);
-
- /* Apply RC4 to data and compute CRC32 over decrypted data */
- plen = skb->len - hdr_len - 8;
-
- crypto_blkcipher_setkey(wep->rx_tfm, key, klen);
- sg_init_one(&sg, pos, plen + 4);
-
- if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4))
- return -7;
-
- crc = ~crc32_le(~0, pos, plen);
- icv[0] = crc;
- icv[1] = crc >> 8;
- icv[2] = crc >> 16;
- icv[3] = crc >> 24;
-
- if (memcmp(icv, pos + plen, 4) != 0) {
- /* ICV mismatch - drop frame */
- return -2;
- }
-
- /* Remove IV and ICV */
- memmove(skb->data + 4, skb->data, hdr_len);
- skb_pull(skb, 4);
- skb_trim(skb, skb->len - 4);
- return 0;
-}
-
-static int prism2_wep_set_key(void *key, int len, u8 *seq, void *priv)
-{
- struct prism2_wep_data *wep = priv;
-
- if (len < 0 || len > WEP_KEY_LEN)
- return -1;
-
- memcpy(wep->key, key, len);
- wep->key_len = len;
-
- return 0;
-}
-
-static int prism2_wep_get_key(void *key, int len, u8 *seq, void *priv)
-{
- struct prism2_wep_data *wep = priv;
-
- if (len < wep->key_len)
- return -1;
-
- memcpy(key, wep->key, wep->key_len);
-
- return wep->key_len;
-}
-
-static char *prism2_wep_print_stats(char *p, void *priv)
-{
- struct prism2_wep_data *wep = priv;
- p += sprintf(p, "key[%d] alg=WEP len=%d\n",
- wep->key_idx, wep->key_len);
- return p;
-}
-
-static struct ieee80211_crypto_ops ieee80211_crypt_wep = {
- .name = "WEP",
- .init = prism2_wep_init,
- .deinit = prism2_wep_deinit,
- .encrypt_mpdu = prism2_wep_encrypt,
- .decrypt_mpdu = prism2_wep_decrypt,
- .encrypt_msdu = NULL,
- .decrypt_msdu = NULL,
- .set_key = prism2_wep_set_key,
- .get_key = prism2_wep_get_key,
- .print_stats = prism2_wep_print_stats,
- .extra_prefix_len = 4, /* IV */
- .extra_postfix_len = 4, /* ICV */
- .owner = THIS_MODULE,
-};
-
-int ieee80211_crypto_wep_init(void)
-{
- return ieee80211_register_crypto_ops(&ieee80211_crypt_wep);
-}
-
-void ieee80211_crypto_wep_exit(void)
-{
- ieee80211_unregister_crypto_ops(&ieee80211_crypt_wep);
-}
-
-void ieee80211_wep_null(void)
-{
- return;
-}
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_module.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_module.c
deleted file mode 100644
index 07a1fbb6678e..000000000000
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_module.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/*******************************************************************************
-
- Copyright(c) 2004 Intel Corporation. All rights reserved.
-
- Portions of this file are based on the WEP enablement code provided by the
- Host AP project hostap-drivers v0.1.3
- Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
- <jkmaline@cc.hut.fi>
- Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of version 2 of the GNU General Public License 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., 59
- Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
- The full GNU General Public License is included in this distribution in the
- file called LICENSE.
-
- Contact Information:
- James P. Ketrenos <ipw2100-admin@linux.intel.com>
- Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-
-*******************************************************************************/
-
-#include <linux/compiler.h>
-//#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/if_arp.h>
-#include <linux/in6.h>
-#include <linux/in.h>
-#include <linux/ip.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/pci.h>
-#include <linux/proc_fs.h>
-#include <linux/skbuff.h>
-#include <linux/slab.h>
-#include <linux/tcp.h>
-#include <linux/types.h>
-#include <linux/wireless.h>
-#include <linux/etherdevice.h>
-#include <linux/uaccess.h>
-#include <net/arp.h>
-#include <net/net_namespace.h>
-
-#include "ieee80211.h"
-
-MODULE_DESCRIPTION("802.11 data/management/control stack");
-MODULE_AUTHOR("Copyright (C) 2004 Intel Corporation <jketreno@linux.intel.com>");
-MODULE_LICENSE("GPL");
-
-#define DRV_NAME "ieee80211"
-
-static inline int ieee80211_networks_allocate(struct ieee80211_device *ieee)
-{
- if (ieee->networks)
- return 0;
-
- ieee->networks = kcalloc(
- MAX_NETWORK_COUNT, sizeof(struct ieee80211_network),
- GFP_KERNEL);
- if (!ieee->networks)
- return -ENOMEM;
-
- return 0;
-}
-
-static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
-{
- if (!ieee->networks)
- return;
- kfree(ieee->networks);
- ieee->networks = NULL;
-}
-
-static inline void ieee80211_networks_initialize(struct ieee80211_device *ieee)
-{
- int i;
-
- INIT_LIST_HEAD(&ieee->network_free_list);
- INIT_LIST_HEAD(&ieee->network_list);
- for (i = 0; i < MAX_NETWORK_COUNT; i++)
- list_add_tail(&ieee->networks[i].list, &ieee->network_free_list);
-}
-
-
-struct net_device *alloc_ieee80211(int sizeof_priv)
-{
- struct ieee80211_device *ieee;
- struct net_device *dev;
- int i, err;
-
- IEEE80211_DEBUG_INFO("Initializing...\n");
-
- dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv);
- if (!dev) {
- IEEE80211_ERROR("Unable to network device.\n");
- goto failed;
- }
- ieee = netdev_priv(dev);
-
- ieee->dev = dev;
-
- err = ieee80211_networks_allocate(ieee);
- if (err) {
- IEEE80211_ERROR("Unable to allocate beacon storage: %d\n",
- err);
- goto failed;
- }
- ieee80211_networks_initialize(ieee);
-
- /* Default fragmentation threshold is maximum payload size */
- ieee->fts = DEFAULT_FTS;
- ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
- ieee->open_wep = 1;
-
- /* Default to enabling full open WEP with host based encrypt/decrypt */
- ieee->host_encrypt = 1;
- ieee->host_decrypt = 1;
- ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
-
- INIT_LIST_HEAD(&ieee->crypt_deinit_list);
- init_timer(&ieee->crypt_deinit_timer);
- ieee->crypt_deinit_timer.data = (unsigned long)ieee;
- ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler;
-
- spin_lock_init(&ieee->lock);
- spin_lock_init(&ieee->wpax_suitlist_lock);
-
- ieee->wpax_type_set = 0;
- ieee->wpa_enabled = 0;
- ieee->tkip_countermeasures = 0;
- ieee->drop_unencrypted = 0;
- ieee->privacy_invoked = 0;
- ieee->ieee802_1x = 1;
- ieee->raw_tx = 0;
-
- ieee80211_softmac_init(ieee);
-
- for (i = 0; i < IEEE_IBSS_MAC_HASH_SIZE; i++)
- INIT_LIST_HEAD(&ieee->ibss_mac_hash[i]);
-
- for (i = 0; i < 17; i++) {
- ieee->last_rxseq_num[i] = -1;
- ieee->last_rxfrag_num[i] = -1;
- ieee->last_packet_time[i] = 0;
- }
-//These function were added to load crypte module autoly
- ieee80211_tkip_null();
- ieee80211_wep_null();
- ieee80211_ccmp_null();
- return dev;
-
- failed:
- if (dev)
- free_netdev(dev);
- return NULL;
-}
-
-
-void free_ieee80211(struct net_device *dev)
-{
- struct ieee80211_device *ieee = netdev_priv(dev);
-
- int i;
- struct list_head *p, *q;
-
-
- ieee80211_softmac_free(ieee);
- del_timer_sync(&ieee->crypt_deinit_timer);
- ieee80211_crypt_deinit_entries(ieee, 1);
-
- for (i = 0; i < WEP_KEYS; i++) {
- struct ieee80211_crypt_data *crypt = ieee->crypt[i];
- if (crypt) {
- if (crypt->ops)
- crypt->ops->deinit(crypt->priv);
- kfree(crypt);
- ieee->crypt[i] = NULL;
- }
- }
-
- ieee80211_networks_free(ieee);
-
- for (i = 0; i < IEEE_IBSS_MAC_HASH_SIZE; i++) {
- list_for_each_safe(p, q, &ieee->ibss_mac_hash[i]) {
- kfree(list_entry(p, struct ieee_ibss_seq, list));
- list_del(p);
- }
- }
-
-
- free_netdev(dev);
-}
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c
deleted file mode 100644
index b522b57a2691..000000000000
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c
+++ /dev/null
@@ -1,1486 +0,0 @@
-/*
- * Original code based Host AP (software wireless LAN access point) driver
- * for Intersil Prism2/2.5/3 - hostap.o module, common routines
- *
- * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
- * <jkmaline@cc.hut.fi>
- * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
- * Copyright (c) 2004, Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation. See README and COPYING for
- * more details.
- ******************************************************************************
-
- Few modifications for Realtek's Wi-Fi drivers by
- Andrea Merello <andrea.merello@gmail.com>
-
- A special thanks goes to Realtek for their support !
-
-******************************************************************************/
-
-
-#include <linux/compiler.h>
-//#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/if_arp.h>
-#include <linux/in6.h>
-#include <linux/in.h>
-#include <linux/ip.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/pci.h>
-#include <linux/proc_fs.h>
-#include <linux/skbuff.h>
-#include <linux/slab.h>
-#include <linux/tcp.h>
-#include <linux/types.h>
-#include <linux/wireless.h>
-#include <linux/etherdevice.h>
-#include <linux/uaccess.h>
-#include <linux/ctype.h>
-
-#include "ieee80211.h"
-#include "dot11d.h"
-static inline void ieee80211_monitor_rx(struct ieee80211_device *ieee,
- struct sk_buff *skb,
- struct ieee80211_rx_stats *rx_stats)
-{
- struct ieee80211_hdr_4addr *hdr =
- (struct ieee80211_hdr_4addr *)skb->data;
- u16 fc = le16_to_cpu(hdr->frame_ctl);
-
- skb->dev = ieee->dev;
- skb_reset_mac_header(skb);
- skb_pull(skb, ieee80211_get_hdrlen(fc));
- skb->pkt_type = PACKET_OTHERHOST;
- skb->protocol = __constant_htons(ETH_P_80211_RAW);
- memset(skb->cb, 0, sizeof(skb->cb));
- netif_rx(skb);
-}
-
-
-/* Called only as a tasklet (software IRQ) */
-static struct ieee80211_frag_entry *
-ieee80211_frag_cache_find(struct ieee80211_device *ieee, unsigned int seq,
- unsigned int frag, u8 tid, u8 *src, u8 *dst)
-{
- struct ieee80211_frag_entry *entry;
- int i;
-
- for (i = 0; i < IEEE80211_FRAG_CACHE_LEN; i++) {
- entry = &ieee->frag_cache[tid][i];
- if (entry->skb != NULL &&
- time_after(jiffies, entry->first_frag_time + 2 * HZ)) {
- IEEE80211_DEBUG_FRAG(
- "expiring fragment cache entry "
- "seq=%u last_frag=%u\n",
- entry->seq, entry->last_frag);
- dev_kfree_skb_any(entry->skb);
- entry->skb = NULL;
- }
-
- if (entry->skb != NULL && entry->seq == seq &&
- (entry->last_frag + 1 == frag || frag == -1) &&
- memcmp(entry->src_addr, src, ETH_ALEN) == 0 &&
- memcmp(entry->dst_addr, dst, ETH_ALEN) == 0)
- return entry;
- }
-
- return NULL;
-}
-
-/* Called only as a tasklet (software IRQ) */
-static struct sk_buff *
-ieee80211_frag_cache_get(struct ieee80211_device *ieee,
- struct ieee80211_hdr_4addr *hdr)
-{
- struct sk_buff *skb = NULL;
- u16 fc = le16_to_cpu(hdr->frame_ctl);
- u16 sc = le16_to_cpu(hdr->seq_ctl);
- unsigned int frag = WLAN_GET_SEQ_FRAG(sc);
- unsigned int seq = WLAN_GET_SEQ_SEQ(sc);
- struct ieee80211_frag_entry *entry;
- struct ieee80211_hdr_3addrqos *hdr_3addrqos;
- struct ieee80211_hdr_4addrqos *hdr_4addrqos;
- u8 tid;
-
- if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) {
- hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)hdr;
- tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QOS_TID;
- tid = UP2AC(tid);
- tid++;
- } else if (IEEE80211_QOS_HAS_SEQ(fc)) {
- hdr_3addrqos = (struct ieee80211_hdr_3addrqos *)hdr;
- tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QOS_TID;
- tid = UP2AC(tid);
- tid++;
- } else {
- tid = 0;
- }
-
- if (frag == 0) {
- /* Reserve enough space to fit maximum frame length */
- skb = dev_alloc_skb(ieee->dev->mtu +
- sizeof(struct ieee80211_hdr_4addr) +
- 8 /* LLC */ +
- 2 /* alignment */ +
- 8 /* WEP */ +
- ETH_ALEN /* WDS */ +
- (IEEE80211_QOS_HAS_SEQ(fc) ? 2 : 0) /* QOS Control */);
- if (skb == NULL)
- return NULL;
-
- entry = &ieee->frag_cache[tid][ieee->frag_next_idx[tid]];
- ieee->frag_next_idx[tid]++;
- if (ieee->frag_next_idx[tid] >= IEEE80211_FRAG_CACHE_LEN)
- ieee->frag_next_idx[tid] = 0;
-
- if (entry->skb != NULL)
- dev_kfree_skb_any(entry->skb);
-
- entry->first_frag_time = jiffies;
- entry->seq = seq;
- entry->last_frag = frag;
- entry->skb = skb;
- memcpy(entry->src_addr, hdr->addr2, ETH_ALEN);
- memcpy(entry->dst_addr, hdr->addr1, ETH_ALEN);
- } else {
- /* received a fragment of a frame for which the head fragment
- * should have already been received */
- entry = ieee80211_frag_cache_find(ieee, seq, frag, tid, hdr->addr2,
- hdr->addr1);
- if (entry != NULL) {
- entry->last_frag = frag;
- skb = entry->skb;
- }
- }
-
- return skb;
-}
-
-
-/* Called only as a tasklet (software IRQ) */
-static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee,
- struct ieee80211_hdr_4addr *hdr)
-{
- u16 fc = le16_to_cpu(hdr->frame_ctl);
- u16 sc = le16_to_cpu(hdr->seq_ctl);
- unsigned int seq = WLAN_GET_SEQ_SEQ(sc);
- struct ieee80211_frag_entry *entry;
- struct ieee80211_hdr_3addrqos *hdr_3addrqos;
- struct ieee80211_hdr_4addrqos *hdr_4addrqos;
- u8 tid;
-
- if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) {
- hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)hdr;
- tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QOS_TID;
- tid = UP2AC(tid);
- tid++;
- } else if (IEEE80211_QOS_HAS_SEQ(fc)) {
- hdr_3addrqos = (struct ieee80211_hdr_3addrqos *)hdr;
- tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QOS_TID;
- tid = UP2AC(tid);
- tid++;
- } else {
- tid = 0;
- }
-
- entry = ieee80211_frag_cache_find(ieee, seq, -1, tid, hdr->addr2,
- hdr->addr1);
-
- if (entry == NULL) {
- IEEE80211_DEBUG_FRAG(
- "could not invalidate fragment cache "
- "entry (seq=%u)\n", seq);
- return -1;
- }
-
- entry->skb = NULL;
- return 0;
-}
-
-
-
-/* ieee80211_rx_frame_mgtmt
- *
- * Responsible for handling management control frames
- *
- * Called by ieee80211_rx */
-static inline int
-ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb,
- struct ieee80211_rx_stats *rx_stats, u16 type,
- u16 stype)
-{
- struct ieee80211_hdr_4addr *hdr;
-
- // cheat the the hdr type
- hdr = (struct ieee80211_hdr_4addr *)skb->data;
-
- /* On the struct stats definition there is written that
- * this is not mandatory.... but seems that the probe
- * response parser uses it
- */
- rx_stats->len = skb->len;
- ieee80211_rx_mgt(ieee, (struct ieee80211_hdr_4addr *)skb->data,
- rx_stats);
-
- if ((ieee->state == IEEE80211_LINKED) && (memcmp(hdr->addr3, ieee->current_network.bssid, ETH_ALEN))) {
- dev_kfree_skb_any(skb);
- return 0;
- }
-
- ieee80211_rx_frame_softmac(ieee, skb, rx_stats, type, stype);
-
- dev_kfree_skb_any(skb);
-
- return 0;
-
-}
-
-
-
-/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
-/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
-static unsigned char rfc1042_header[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
-/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
-static unsigned char bridge_tunnel_header[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
-/* No encapsulation header if EtherType < 0x600 (=length) */
-
-/* Called by ieee80211_rx_frame_decrypt */
-static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee,
- struct sk_buff *skb, size_t hdrlen)
-{
- struct net_device *dev = ieee->dev;
- u16 fc, ethertype;
- struct ieee80211_hdr_4addr *hdr;
- u8 *pos;
-
- if (skb->len < 24)
- return 0;
-
- hdr = (struct ieee80211_hdr_4addr *)skb->data;
- fc = le16_to_cpu(hdr->frame_ctl);
-
- /* check that the frame is unicast frame to us */
- if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
- IEEE80211_FCTL_TODS &&
- memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0 &&
- memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) {
- /* ToDS frame with own addr BSSID and DA */
- } else if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
- IEEE80211_FCTL_FROMDS &&
- memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) {
- /* FromDS frame with own addr as DA */
- } else
- return 0;
-
- if (skb->len < 24 + 8)
- return 0;
-
- /* check for port access entity Ethernet type */
-// pos = skb->data + 24;
- pos = skb->data + hdrlen;
- ethertype = (pos[6] << 8) | pos[7];
- if (ethertype == ETH_P_PAE)
- return 1;
-
- return 0;
-}
-
-/* Called only as a tasklet (software IRQ), by ieee80211_rx */
-static inline int
-ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb,
- struct ieee80211_crypt_data *crypt)
-{
- struct ieee80211_hdr_4addr *hdr;
- int res, hdrlen;
-
- if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
- return 0;
-
- hdr = (struct ieee80211_hdr_4addr *)skb->data;
- hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
-
-#ifdef CONFIG_IEEE80211_CRYPT_TKIP
- if (ieee->tkip_countermeasures &&
- strcmp(crypt->ops->name, "TKIP") == 0) {
- if (net_ratelimit()) {
- netdev_dbg(ieee->dev,
- "TKIP countermeasures: dropped received packet from %pM\n",
- ieee->dev->name, hdr->addr2);
- }
- return -1;
- }
-#endif
-
- atomic_inc(&crypt->refcnt);
- res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
- atomic_dec(&crypt->refcnt);
- if (res < 0) {
- IEEE80211_DEBUG_DROP(
- "decryption failed (SA=%pM"
- ") res=%d\n", hdr->addr2, res);
- if (res == -2)
- IEEE80211_DEBUG_DROP("Decryption failed ICV "
- "mismatch (key %d)\n",
- skb->data[hdrlen + 3] >> 6);
- ieee->ieee_stats.rx_discards_undecryptable++;
- return -1;
- }
-
- return res;
-}
-
-
-/* Called only as a tasklet (software IRQ), by ieee80211_rx */
-static inline int
-ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee,
- struct sk_buff *skb, int keyidx,
- struct ieee80211_crypt_data *crypt)
-{
- struct ieee80211_hdr_4addr *hdr;
- int res, hdrlen;
-
- if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
- return 0;
-
- hdr = (struct ieee80211_hdr_4addr *)skb->data;
- hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
-
- atomic_inc(&crypt->refcnt);
- res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv);
- atomic_dec(&crypt->refcnt);
- if (res < 0) {
- netdev_dbg(ieee->dev,
- "MSDU decryption/MIC verification failed (SA=%pM keyidx=%d)\n",
- hdr->addr2, keyidx);
- return -1;
- }
-
- return 0;
-}
-
-
-/* this function is stolen from ipw2200 driver*/
-#define IEEE_PACKET_RETRY_TIME (5*HZ)
-static int is_duplicate_packet(struct ieee80211_device *ieee,
- struct ieee80211_hdr_4addr *header)
-{
- u16 fc = le16_to_cpu(header->frame_ctl);
- u16 sc = le16_to_cpu(header->seq_ctl);
- u16 seq = WLAN_GET_SEQ_SEQ(sc);
- u16 frag = WLAN_GET_SEQ_FRAG(sc);
- u16 *last_seq, *last_frag;
- unsigned long *last_time;
- struct ieee80211_hdr_3addrqos *hdr_3addrqos;
- struct ieee80211_hdr_4addrqos *hdr_4addrqos;
- u8 tid;
-
- //TO2DS and QoS
- if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) {
- hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)header;
- tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QOS_TID;
- tid = UP2AC(tid);
- tid++;
- } else if (IEEE80211_QOS_HAS_SEQ(fc)) { //QoS
- hdr_3addrqos = (struct ieee80211_hdr_3addrqos *)header;
- tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QOS_TID;
- tid = UP2AC(tid);
- tid++;
- } else { // no QoS
- tid = 0;
- }
- switch (ieee->iw_mode) {
- case IW_MODE_ADHOC:
- {
- struct list_head *p;
- struct ieee_ibss_seq *entry = NULL;
- u8 *mac = header->addr2;
- int index = mac[5] % IEEE_IBSS_MAC_HASH_SIZE;
-
- list_for_each(p, &ieee->ibss_mac_hash[index]) {
- entry = list_entry(p, struct ieee_ibss_seq, list);
- if (!memcmp(entry->mac, mac, ETH_ALEN))
- break;
- }
- // if (memcmp(entry->mac, mac, ETH_ALEN)){
- if (p == &ieee->ibss_mac_hash[index]) {
- entry = kmalloc(sizeof(struct ieee_ibss_seq), GFP_ATOMIC);
- if (!entry)
- return 0;
-
- memcpy(entry->mac, mac, ETH_ALEN);
- entry->seq_num[tid] = seq;
- entry->frag_num[tid] = frag;
- entry->packet_time[tid] = jiffies;
- list_add(&entry->list, &ieee->ibss_mac_hash[index]);
- return 0;
- }
- last_seq = &entry->seq_num[tid];
- last_frag = &entry->frag_num[tid];
- last_time = &entry->packet_time[tid];
- break;
- }
-
- case IW_MODE_INFRA:
- last_seq = &ieee->last_rxseq_num[tid];
- last_frag = &ieee->last_rxfrag_num[tid];
- last_time = &ieee->last_packet_time[tid];
-
- break;
- default:
- return 0;
- }
-
-// if(tid != 0) {
-// printk(KERN_WARNING ":)))))))))))%x %x %x, fc(%x)\n", tid, *last_seq, seq, header->frame_ctl);
-// }
- if ((*last_seq == seq) &&
- time_after(*last_time + IEEE_PACKET_RETRY_TIME, jiffies)) {
- if (*last_frag == frag) {
- //printk(KERN_WARNING "[1] go drop!\n");
- goto drop;
-
- }
- if (*last_frag + 1 != frag)
- /* out-of-order fragment */
- //printk(KERN_WARNING "[2] go drop!\n");
- goto drop;
- } else
- *last_seq = seq;
-
- *last_frag = frag;
- *last_time = jiffies;
- return 0;
-
-drop:
-// BUG_ON(!(fc & IEEE80211_FCTL_RETRY));
-// printk("DUP\n");
-
- return 1;
-}
-
-
-/* All received frames are sent to this function. @skb contains the frame in
- * IEEE 802.11 format, i.e., in the format it was sent over air.
- * This function is called only as a tasklet (software IRQ). */
-int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
- struct ieee80211_rx_stats *rx_stats)
-{
- struct net_device *dev = ieee->dev;
- //struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- struct ieee80211_hdr_4addr *hdr;
-
- size_t hdrlen;
- u16 fc, type, stype, sc;
- struct net_device_stats *stats;
- unsigned int frag;
- u8 *payload;
- u16 ethertype;
- u8 dst[ETH_ALEN];
- u8 src[ETH_ALEN];
- u8 bssid[ETH_ALEN];
- struct ieee80211_crypt_data *crypt = NULL;
- int keyidx = 0;
-
- // cheat the the hdr type
- hdr = (struct ieee80211_hdr_4addr *)skb->data;
- stats = &ieee->stats;
-
- if (skb->len < 10) {
- netdev_info(ieee->dev, "SKB length < 10\n");
- goto rx_dropped;
- }
-
- fc = le16_to_cpu(hdr->frame_ctl);
- type = WLAN_FC_GET_TYPE(fc);
- stype = WLAN_FC_GET_STYPE(fc);
- sc = le16_to_cpu(hdr->seq_ctl);
-
- frag = WLAN_GET_SEQ_FRAG(sc);
-
-//YJ,add,080828,for keep alive
- if ((fc & IEEE80211_FCTL_TODS) != IEEE80211_FCTL_TODS) {
- if (!memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN))
- ieee->NumRxUnicast++;
- } else {
- if (!memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN))
- ieee->NumRxUnicast++;
- }
-//YJ,add,080828,for keep alive,end
-
- hdrlen = ieee80211_get_hdrlen(fc);
-
-
- if (ieee->iw_mode == IW_MODE_MONITOR) {
- ieee80211_monitor_rx(ieee, skb, rx_stats);
- stats->rx_packets++;
- stats->rx_bytes += skb->len;
- return 1;
- }
-
- if (ieee->host_decrypt) {
- int idx = 0;
- if (skb->len >= hdrlen + 3)
- idx = skb->data[hdrlen + 3] >> 6;
- crypt = ieee->crypt[idx];
-
- /* allow NULL decrypt to indicate an station specific override
- * for default encryption */
- if (crypt && (crypt->ops == NULL ||
- crypt->ops->decrypt_mpdu == NULL))
- crypt = NULL;
-
- if (!crypt && (fc & IEEE80211_FCTL_WEP)) {
- /* This seems to be triggered by some (multicast?)
- * frames from other than current BSS, so just drop the
- * frames silently instead of filling system log with
- * these reports. */
- IEEE80211_DEBUG_DROP("Decryption failed (not set)"
- " (SA=%pM)\n",
- hdr->addr2);
- ieee->ieee_stats.rx_discards_undecryptable++;
- goto rx_dropped;
- }
- }
-
- if (skb->len < IEEE80211_DATA_HDR3_LEN)
- goto rx_dropped;
-
- // if QoS enabled, should check the sequence for each of the AC
- if (is_duplicate_packet(ieee, hdr))
- goto rx_dropped;
-
-
- if (type == IEEE80211_FTYPE_MGMT) {
- if (ieee80211_rx_frame_mgmt(ieee, skb, rx_stats, type, stype))
- goto rx_dropped;
- else
- goto rx_exit;
- }
-
- /* Data frame - extract src/dst addresses */
- switch (fc & (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
- case IEEE80211_FCTL_FROMDS:
- memcpy(dst, hdr->addr1, ETH_ALEN);
- memcpy(src, hdr->addr3, ETH_ALEN);
- memcpy(bssid, hdr->addr2, ETH_ALEN);
- break;
- case IEEE80211_FCTL_TODS:
- memcpy(dst, hdr->addr3, ETH_ALEN);
- memcpy(src, hdr->addr2, ETH_ALEN);
- memcpy(bssid, hdr->addr1, ETH_ALEN);
- break;
- case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
- if (skb->len < IEEE80211_DATA_HDR4_LEN)
- goto rx_dropped;
- memcpy(dst, hdr->addr3, ETH_ALEN);
- memcpy(src, hdr->addr4, ETH_ALEN);
- memcpy(bssid, ieee->current_network.bssid, ETH_ALEN);
- break;
- case 0:
- memcpy(dst, hdr->addr1, ETH_ALEN);
- memcpy(src, hdr->addr2, ETH_ALEN);
- memcpy(bssid, hdr->addr3, ETH_ALEN);
- break;
- }
-
-
- dev->last_rx = jiffies;
-
-
- /* Nullfunc frames may have PS-bit set, so they must be passed to
- * hostap_handle_sta_rx() before being dropped here. */
- if (stype != IEEE80211_STYPE_DATA &&
- stype != IEEE80211_STYPE_DATA_CFACK &&
- stype != IEEE80211_STYPE_DATA_CFPOLL &&
- stype != IEEE80211_STYPE_DATA_CFACKPOLL &&
- stype != IEEE80211_STYPE_QOS_DATA//add by David,2006.8.4
- ) {
- if (stype != IEEE80211_STYPE_NULLFUNC)
- IEEE80211_DEBUG_DROP(
- "RX: dropped data frame "
- "with no data (type=0x%02x, "
- "subtype=0x%02x, len=%d)\n",
- type, stype, skb->len);
- goto rx_dropped;
- }
- if (memcmp(bssid, ieee->current_network.bssid, ETH_ALEN))
- goto rx_dropped;
-
- ieee->NumRxDataInPeriod++;
- ieee->NumRxOkTotal++;
- /* skb: hdr + (possibly fragmented, possibly encrypted) payload */
-
- if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
- (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0)
- goto rx_dropped;
-
- hdr = (struct ieee80211_hdr_4addr *)skb->data;
-
- /* skb: hdr + (possibly fragmented) plaintext payload */
- // PR: FIXME: hostap has additional conditions in the "if" below:
- // ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
- if ((frag != 0 || (fc & IEEE80211_FCTL_MOREFRAGS))) {
- int flen;
- struct sk_buff *frag_skb = ieee80211_frag_cache_get(ieee, hdr);
- IEEE80211_DEBUG_FRAG("Rx Fragment received (%u)\n", frag);
-
- if (!frag_skb) {
- IEEE80211_DEBUG(IEEE80211_DL_RX | IEEE80211_DL_FRAG,
- "Rx cannot get skb from fragment "
- "cache (morefrag=%d seq=%u frag=%u)\n",
- (fc & IEEE80211_FCTL_MOREFRAGS) != 0,
- WLAN_GET_SEQ_SEQ(sc), frag);
- goto rx_dropped;
- }
- flen = skb->len;
- if (frag != 0)
- flen -= hdrlen;
-
- if (frag_skb->tail + flen > frag_skb->end) {
- netdev_warn(ieee->dev,
- "host decrypted and reassembled frame did not fit skb\n");
- ieee80211_frag_cache_invalidate(ieee, hdr);
- goto rx_dropped;
- }
-
- if (frag == 0) {
- /* copy first fragment (including full headers) into
- * beginning of the fragment cache skb */
- memcpy(skb_put(frag_skb, flen), skb->data, flen);
- } else {
- /* append frame payload to the end of the fragment
- * cache skb */
- memcpy(skb_put(frag_skb, flen), skb->data + hdrlen,
- flen);
- }
- dev_kfree_skb_any(skb);
- skb = NULL;
-
- if (fc & IEEE80211_FCTL_MOREFRAGS) {
- /* more fragments expected - leave the skb in fragment
- * cache for now; it will be delivered to upper layers
- * after all fragments have been received */
- goto rx_exit;
- }
-
- /* this was the last fragment and the frame will be
- * delivered, so remove skb from fragment cache */
- skb = frag_skb;
- hdr = (struct ieee80211_hdr_4addr *)skb->data;
- ieee80211_frag_cache_invalidate(ieee, hdr);
- }
-
- /* skb: hdr + (possible reassembled) full MSDU payload; possibly still
- * encrypted/authenticated */
- if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
- ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt))
- goto rx_dropped;
-
- hdr = (struct ieee80211_hdr_4addr *)skb->data;
- if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep) {
- if (/*ieee->ieee802_1x &&*/
- ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
-
-#ifdef CONFIG_IEEE80211_DEBUG
- /* pass unencrypted EAPOL frames even if encryption is
- * configured */
- struct eapol *eap = (struct eapol *)(skb->data +
- 24);
- IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
- eap_get_type(eap->type));
-#endif
- } else {
- IEEE80211_DEBUG_DROP(
- "encryption configured, but RX "
- "frame not encrypted (SA=%pM)\n",
- hdr->addr2);
- goto rx_dropped;
- }
- }
-
-#ifdef CONFIG_IEEE80211_DEBUG
- if (crypt && !(fc & IEEE80211_FCTL_WEP) &&
- ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
- struct eapol *eap = (struct eapol *)(skb->data +
- 24);
- IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
- eap_get_type(eap->type));
- }
-#endif
-
- if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep &&
- !ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
- IEEE80211_DEBUG_DROP(
- "dropped unencrypted RX data "
- "frame from %pM"
- " (drop_unencrypted=1)\n",
- hdr->addr2);
- goto rx_dropped;
- }
-/*
- if(ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
- printk(KERN_WARNING "RX: IEEE802.1X EPAOL frame!\n");
- }
-*/
- /* skb: hdr + (possible reassembled) full plaintext payload */
- payload = skb->data + hdrlen;
- ethertype = (payload[6] << 8) | payload[7];
-
-
- /* convert hdr + possible LLC headers into Ethernet header */
- if (skb->len - hdrlen >= 8 &&
- ((memcmp(payload, rfc1042_header, SNAP_SIZE) == 0 &&
- ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
- memcmp(payload, bridge_tunnel_header, SNAP_SIZE) == 0)) {
- /* remove RFC1042 or Bridge-Tunnel encapsulation and
- * replace EtherType */
- skb_pull(skb, hdrlen + SNAP_SIZE);
- memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
- memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
- } else {
- u16 len;
- /* Leave Ethernet header part of hdr and full payload */
- skb_pull(skb, hdrlen);
- len = htons(skb->len);
- memcpy(skb_push(skb, 2), &len, 2);
- memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
- memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
- }
-
-
- stats->rx_packets++;
- stats->rx_bytes += skb->len;
-
- if (skb) {
- skb->protocol = eth_type_trans(skb, dev);
- memset(skb->cb, 0, sizeof(skb->cb));
- skb->dev = dev;
- skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */
- ieee->last_rx_ps_time = jiffies;
- netif_rx(skb);
- }
-
- rx_exit:
- return 1;
-
- rx_dropped:
- stats->rx_dropped++;
-
- /* Returning 0 indicates to caller that we have not handled the SKB--
- * so it is still allocated and can be used again by underlying
- * hardware as a DMA target */
- return 0;
-}
-
-#define MGMT_FRAME_FIXED_PART_LENGTH 0x24
-
-static inline int ieee80211_is_ofdm_rate(u8 rate)
-{
- switch (rate & ~IEEE80211_BASIC_RATE_MASK) {
- case IEEE80211_OFDM_RATE_6MB:
- case IEEE80211_OFDM_RATE_9MB:
- case IEEE80211_OFDM_RATE_12MB:
- case IEEE80211_OFDM_RATE_18MB:
- case IEEE80211_OFDM_RATE_24MB:
- case IEEE80211_OFDM_RATE_36MB:
- case IEEE80211_OFDM_RATE_48MB:
- case IEEE80211_OFDM_RATE_54MB:
- return 1;
- }
- return 0;
-}
-
-static inline int ieee80211_SignalStrengthTranslate(int CurrSS)
-{
- int RetSS;
-
- // Step 1. Scale mapping.
- if (CurrSS >= 71 && CurrSS <= 100)
- RetSS = 90 + ((CurrSS - 70) / 3);
- else if (CurrSS >= 41 && CurrSS <= 70)
- RetSS = 78 + ((CurrSS - 40) / 3);
- else if (CurrSS >= 31 && CurrSS <= 40)
- RetSS = 66 + (CurrSS - 30);
- else if (CurrSS >= 21 && CurrSS <= 30)
- RetSS = 54 + (CurrSS - 20);
- else if (CurrSS >= 5 && CurrSS <= 20)
- RetSS = 42 + (((CurrSS - 5) * 2) / 3);
- else if (CurrSS == 4)
- RetSS = 36;
- else if (CurrSS == 3)
- RetSS = 27;
- else if (CurrSS == 2)
- RetSS = 18;
- else if (CurrSS == 1)
- RetSS = 9;
- else
- RetSS = CurrSS;
-
- //RT_TRACE(COMP_DBG, DBG_LOUD, ("##### After Mapping: LastSS: %d, CurrSS: %d, RetSS: %d\n", LastSS, CurrSS, RetSS));
-
- // Step 2. Smoothing.
-
- //RT_TRACE(COMP_DBG, DBG_LOUD, ("$$$$$ After Smoothing: LastSS: %d, CurrSS: %d, RetSS: %d\n", LastSS, CurrSS, RetSS));
-
- return RetSS;
-}
-
-static inline void
-ieee80211_extract_country_ie(struct ieee80211_device *ieee,
- struct ieee80211_info_element *info_element,
- struct ieee80211_network *network, u8 *addr2)
-{
- if (IS_DOT11D_ENABLE(ieee)) {
- if (info_element->len != 0) {
- memcpy(network->CountryIeBuf, info_element->data, info_element->len);
- network->CountryIeLen = info_element->len;
-
- if (!IS_COUNTRY_IE_VALID(ieee))
- Dot11d_UpdateCountryIe(ieee, addr2, info_element->len, info_element->data);
- }
-
- //
- // 070305, rcnjko: I update country IE watch dog here because
- // some AP (e.g. Cisco 1242) don't include country IE in their
- // probe response frame.
- //
- if (IS_EQUAL_CIE_SRC(ieee, addr2))
- UPDATE_CIE_WATCHDOG(ieee);
- }
-
-}
-
-/* SignalStrengthIndex is 0-100 */
-static int ieee80211_TranslateToDbm(unsigned char SignalStrengthIndex)
-{
- unsigned char SignalPower; // in dBm.
-
- // Translate to dBm (x=0.5y-95).
- SignalPower = (int)SignalStrengthIndex * 7 / 10;
- SignalPower -= 95;
-
- return SignalPower;
-}
-inline int ieee80211_network_init(
- struct ieee80211_device *ieee,
- struct ieee80211_probe_response *beacon,
- struct ieee80211_network *network,
- struct ieee80211_rx_stats *stats)
-{
-#ifdef CONFIG_IEEE80211_DEBUG
- char rates_str[64];
- char *p;
-#endif
- struct ieee80211_info_element *info_element;
- u16 left;
- u8 i;
- short offset;
- u8 curRate = 0, hOpRate = 0, curRate_ex = 0;
-
- /* Pull out fixed field data */
- memcpy(network->bssid, beacon->header.addr3, ETH_ALEN);
- network->capability = beacon->capability;
- network->last_scanned = jiffies;
- network->time_stamp[0] = beacon->time_stamp[0];
- network->time_stamp[1] = beacon->time_stamp[1];
- network->beacon_interval = beacon->beacon_interval;
- /* Where to pull this? beacon->listen_interval;*/
- network->listen_interval = 0x0A;
- network->rates_len = network->rates_ex_len = 0;
- network->last_associate = 0;
- network->ssid_len = 0;
- network->flags = 0;
- network->atim_window = 0;
- network->QoS_Enable = 0;
-//by amy 080312
- network->HighestOperaRate = 0;
-//by amy 080312
- network->Turbo_Enable = 0;
- network->CountryIeLen = 0;
- memset(network->CountryIeBuf, 0, MAX_IE_LEN);
-
- if (stats->freq == IEEE80211_52GHZ_BAND) {
- /* for A band (No DS info) */
- network->channel = stats->received_channel;
- } else
- network->flags |= NETWORK_HAS_CCK;
-
- network->wpa_ie_len = 0;
- network->rsn_ie_len = 0;
-
- info_element = &beacon->info_element;
- left = stats->len - ((void *)info_element - (void *)beacon);
- while (left >= sizeof(struct ieee80211_info_element_hdr)) {
- if (sizeof(struct ieee80211_info_element_hdr) + info_element->len > left) {
- IEEE80211_DEBUG_SCAN("SCAN: parse failed: info_element->len + 2 > left : info_element->len+2=%d left=%d.\n",
- info_element->len + sizeof(struct ieee80211_info_element),
- left);
- return 1;
- }
-
- switch (info_element->id) {
- case MFIE_TYPE_SSID:
- if (ieee80211_is_empty_essid(info_element->data,
- info_element->len)) {
- network->flags |= NETWORK_EMPTY_ESSID;
- break;
- }
-
- network->ssid_len = min(info_element->len,
- (u8)IW_ESSID_MAX_SIZE);
- memcpy(network->ssid, info_element->data, network->ssid_len);
- if (network->ssid_len < IW_ESSID_MAX_SIZE)
- memset(network->ssid + network->ssid_len, 0,
- IW_ESSID_MAX_SIZE - network->ssid_len);
-
- IEEE80211_DEBUG_SCAN("MFIE_TYPE_SSID: '%s' len=%d.\n",
- network->ssid, network->ssid_len);
- break;
-
- case MFIE_TYPE_RATES:
-#ifdef CONFIG_IEEE80211_DEBUG
- p = rates_str;
-#endif
- network->rates_len = min(info_element->len, MAX_RATES_LENGTH);
- for (i = 0; i < network->rates_len; i++) {
- network->rates[i] = info_element->data[i];
- curRate = network->rates[i] & 0x7f;
- if (hOpRate < curRate)
- hOpRate = curRate;
-#ifdef CONFIG_IEEE80211_DEBUG
- p += snprintf(p, sizeof(rates_str) - (p - rates_str), "%02X ", network->rates[i]);
-#endif
- if (ieee80211_is_ofdm_rate(info_element->data[i])) {
- network->flags |= NETWORK_HAS_OFDM;
- if (info_element->data[i] &
- IEEE80211_BASIC_RATE_MASK)
- network->flags &=
- ~NETWORK_HAS_CCK;
- }
- }
-
- IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES: '%s' (%d)\n",
- rates_str, network->rates_len);
- break;
-
- case MFIE_TYPE_RATES_EX:
-#ifdef CONFIG_IEEE80211_DEBUG
- p = rates_str;
-#endif
- network->rates_ex_len = min(info_element->len, MAX_RATES_EX_LENGTH);
- for (i = 0; i < network->rates_ex_len; i++) {
- network->rates_ex[i] = info_element->data[i];
- curRate_ex = network->rates_ex[i] & 0x7f;
- if (hOpRate < curRate_ex)
- hOpRate = curRate_ex;
-#ifdef CONFIG_IEEE80211_DEBUG
- p += snprintf(p, sizeof(rates_str) - (p - rates_str), "%02X ", network->rates[i]);
-#endif
- if (ieee80211_is_ofdm_rate(info_element->data[i])) {
- network->flags |= NETWORK_HAS_OFDM;
- if (info_element->data[i] &
- IEEE80211_BASIC_RATE_MASK)
- network->flags &=
- ~NETWORK_HAS_CCK;
- }
- }
-
- IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES_EX: '%s' (%d)\n",
- rates_str, network->rates_ex_len);
- break;
-
- case MFIE_TYPE_DS_SET:
- IEEE80211_DEBUG_SCAN("MFIE_TYPE_DS_SET: %d\n",
- info_element->data[0]);
- if (stats->freq == IEEE80211_24GHZ_BAND)
- network->channel = info_element->data[0];
- break;
-
- case MFIE_TYPE_FH_SET:
- IEEE80211_DEBUG_SCAN("MFIE_TYPE_FH_SET: ignored\n");
- break;
-
- case MFIE_TYPE_CF_SET:
- IEEE80211_DEBUG_SCAN("MFIE_TYPE_CF_SET: ignored\n");
- break;
-
- case MFIE_TYPE_TIM:
-
- if (info_element->len < 4)
- break;
-
- network->dtim_period = info_element->data[1];
-
- if (ieee->state != IEEE80211_LINKED)
- break;
-
- network->last_dtim_sta_time[0] = jiffies;
- network->last_dtim_sta_time[1] = stats->mac_time[1];
-
- network->dtim_data = IEEE80211_DTIM_VALID;
-
- if (info_element->data[0] != 0)
- break;
-
- if (info_element->data[2] & 1)
- network->dtim_data |= IEEE80211_DTIM_MBCAST;
-
- offset = (info_element->data[2] >> 1)*2;
-
- //printk("offset1:%x aid:%x\n",offset, ieee->assoc_id);
-
- /* add and modified for ps 2008.1.22 */
- if (ieee->assoc_id < 8*offset ||
- ieee->assoc_id > 8*(offset + info_element->len - 3)) {
- break;
- }
-
- offset = (ieee->assoc_id/8) - offset;// + ((aid % 8)? 0 : 1) ;
-
- // printk("offset:%x data:%x, ucast:%d\n", offset,
- // info_element->data[3+offset] ,
- // info_element->data[3+offset] & (1<<(ieee->assoc_id%8)));
-
- if (info_element->data[3+offset] & (1<<(ieee->assoc_id%8)))
- network->dtim_data |= IEEE80211_DTIM_UCAST;
-
- break;
-
- case MFIE_TYPE_IBSS_SET:
- IEEE80211_DEBUG_SCAN("MFIE_TYPE_IBSS_SET: ignored\n");
- break;
-
- case MFIE_TYPE_CHALLENGE:
- IEEE80211_DEBUG_SCAN("MFIE_TYPE_CHALLENGE: ignored\n");
- break;
-
- case MFIE_TYPE_GENERIC:
- //nic is 87B
- IEEE80211_DEBUG_SCAN("MFIE_TYPE_GENERIC: %d bytes\n",
- info_element->len);
- if (info_element->len >= 4 &&
- info_element->data[0] == 0x00 &&
- info_element->data[1] == 0x50 &&
- info_element->data[2] == 0xf2 &&
- info_element->data[3] == 0x01) {
- network->wpa_ie_len = min(info_element->len + 2,
- MAX_WPA_IE_LEN);
- memcpy(network->wpa_ie, info_element,
- network->wpa_ie_len);
- }
-
- if (info_element->len == 7 &&
- info_element->data[0] == 0x00 &&
- info_element->data[1] == 0xe0 &&
- info_element->data[2] == 0x4c &&
- info_element->data[3] == 0x01 &&
- info_element->data[4] == 0x02) {
- network->Turbo_Enable = 1;
- }
- if (1 == stats->nic_type) //nic 87
- break;
-
- if (info_element->len >= 5 &&
- info_element->data[0] == 0x00 &&
- info_element->data[1] == 0x50 &&
- info_element->data[2] == 0xf2 &&
- info_element->data[3] == 0x02 &&
- info_element->data[4] == 0x00) {
- //printk(KERN_WARNING "wmm info updated: %x\n", info_element->data[6]);
- //WMM Information Element
- network->wmm_info = info_element->data[6];
- network->QoS_Enable = 1;
- }
-
- if (info_element->len >= 8 &&
- info_element->data[0] == 0x00 &&
- info_element->data[1] == 0x50 &&
- info_element->data[2] == 0xf2 &&
- info_element->data[3] == 0x02 &&
- info_element->data[4] == 0x01) {
- // Not care about version at present.
- //WMM Information Element
- //printk(KERN_WARNING "wmm info&param updated: %x\n", info_element->data[6]);
- network->wmm_info = info_element->data[6];
- //WMM Parameter Element
- memcpy(network->wmm_param, (u8 *)(info_element->data + 8), (info_element->len - 8));
- network->QoS_Enable = 1;
- }
- break;
-
- case MFIE_TYPE_RSN:
- IEEE80211_DEBUG_SCAN("MFIE_TYPE_RSN: %d bytes\n",
- info_element->len);
- network->rsn_ie_len = min(info_element->len + 2,
- MAX_WPA_IE_LEN);
- memcpy(network->rsn_ie, info_element,
- network->rsn_ie_len);
- break;
- case MFIE_TYPE_COUNTRY:
- IEEE80211_DEBUG_SCAN("MFIE_TYPE_COUNTRY: %d bytes\n",
- info_element->len);
-// printk("=====>Receive <%s> Country IE\n",network->ssid);
- ieee80211_extract_country_ie(ieee, info_element, network, beacon->header.addr2);
- break;
- default:
- IEEE80211_DEBUG_SCAN("unsupported IE %d\n",
- info_element->id);
- break;
- }
-
- left -= sizeof(struct ieee80211_info_element_hdr) +
- info_element->len;
- info_element = (struct ieee80211_info_element *)
- &info_element->data[info_element->len];
- }
-//by amy 080312
- network->HighestOperaRate = hOpRate;
-//by amy 080312
- network->mode = 0;
- if (stats->freq == IEEE80211_52GHZ_BAND)
- network->mode = IEEE_A;
- else {
- if (network->flags & NETWORK_HAS_OFDM)
- network->mode |= IEEE_G;
- if (network->flags & NETWORK_HAS_CCK)
- network->mode |= IEEE_B;
- }
-
- if (network->mode == 0) {
- IEEE80211_DEBUG_SCAN("Filtered out '%s (%pM)' "
- "network.\n",
- escape_essid(network->ssid,
- network->ssid_len),
- network->bssid);
- return 1;
- }
-
- if (ieee80211_is_empty_essid(network->ssid, network->ssid_len))
- network->flags |= NETWORK_EMPTY_ESSID;
-
- stats->signal = ieee80211_TranslateToDbm(stats->signalstrength);
- //stats->noise = stats->signal - stats->noise;
- stats->noise = ieee80211_TranslateToDbm(100 - stats->signalstrength) - 25;
- memcpy(&network->stats, stats, sizeof(network->stats));
-
- return 0;
-}
-
-static inline int is_same_network(struct ieee80211_network *src,
- struct ieee80211_network *dst,
- struct ieee80211_device *ieee)
-{
- /* A network is only a duplicate if the channel, BSSID, ESSID
- * and the capability field (in particular IBSS and BSS) all match.
- * We treat all <hidden> with the same BSSID and channel
- * as one network */
- return (((src->ssid_len == dst->ssid_len) || (ieee->iw_mode == IW_MODE_INFRA)) && //YJ,mod,080819,for hidden ap
- //((src->ssid_len == dst->ssid_len) &&
- (src->channel == dst->channel) &&
- !memcmp(src->bssid, dst->bssid, ETH_ALEN) &&
- (!memcmp(src->ssid, dst->ssid, src->ssid_len) || (ieee->iw_mode == IW_MODE_INFRA)) && //YJ,mod,080819,for hidden ap
- //!memcmp(src->ssid, dst->ssid, src->ssid_len) &&
- ((src->capability & WLAN_CAPABILITY_IBSS) ==
- (dst->capability & WLAN_CAPABILITY_IBSS)) &&
- ((src->capability & WLAN_CAPABILITY_BSS) ==
- (dst->capability & WLAN_CAPABILITY_BSS)));
-}
-
-inline void update_network(struct ieee80211_network *dst,
- struct ieee80211_network *src)
-{
- unsigned char quality = src->stats.signalstrength;
- unsigned char signal = 0;
- unsigned char noise = 0;
- if (dst->stats.signalstrength > 0)
- quality = (dst->stats.signalstrength * 5 + src->stats.signalstrength + 5)/6;
- signal = ieee80211_TranslateToDbm(quality);
- //noise = signal - src->stats.noise;
- if (dst->stats.noise > 0)
- noise = (dst->stats.noise * 5 + src->stats.noise)/6;
- //if(strcmp(dst->ssid, "linksys_lzm000") == 0)
-// printk("ssid:%s, quality:%d, signal:%d\n", dst->ssid, quality, signal);
- memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats));
- dst->stats.signalstrength = quality;
- dst->stats.signal = signal;
-// printk("==================>stats.signal is %d\n",dst->stats.signal);
- dst->stats.noise = noise;
-
-
- dst->capability = src->capability;
- memcpy(dst->rates, src->rates, src->rates_len);
- dst->rates_len = src->rates_len;
- memcpy(dst->rates_ex, src->rates_ex, src->rates_ex_len);
- dst->rates_ex_len = src->rates_ex_len;
- dst->HighestOperaRate = src->HighestOperaRate;
- //printk("==========>in %s: src->ssid is %s,chan is %d\n",__func__,src->ssid,src->channel);
-
- //YJ,add,080819,for hidden ap
- if (src->ssid_len > 0) {
- //if(src->ssid_len == 13)
- // printk("=====================>>>>>>>> Dst ssid: %s Src ssid: %s\n", dst->ssid, src->ssid);
- memset(dst->ssid, 0, dst->ssid_len);
- dst->ssid_len = src->ssid_len;
- memcpy(dst->ssid, src->ssid, src->ssid_len);
- }
- //YJ,add,080819,for hidden ap,end
-
- dst->channel = src->channel;
- dst->mode = src->mode;
- dst->flags = src->flags;
- dst->time_stamp[0] = src->time_stamp[0];
- dst->time_stamp[1] = src->time_stamp[1];
-
- dst->beacon_interval = src->beacon_interval;
- dst->listen_interval = src->listen_interval;
- dst->atim_window = src->atim_window;
- dst->dtim_period = src->dtim_period;
- dst->dtim_data = src->dtim_data;
- dst->last_dtim_sta_time[0] = src->last_dtim_sta_time[0];
- dst->last_dtim_sta_time[1] = src->last_dtim_sta_time[1];
-// printk("update:%s, dtim_period:%x, dtim_data:%x\n", src->ssid, src->dtim_period, src->dtim_data);
- memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len);
- dst->wpa_ie_len = src->wpa_ie_len;
- memcpy(dst->rsn_ie, src->rsn_ie, src->rsn_ie_len);
- dst->rsn_ie_len = src->rsn_ie_len;
-
- dst->last_scanned = jiffies;
- /* dst->last_associate is not overwritten */
-// disable QoS process now, added by David 2006/7/25
-#if 1
- dst->wmm_info = src->wmm_info; //sure to exist in beacon or probe response frame.
-/*
- if((dst->wmm_info^src->wmm_info)&0x0f) {//Param Set Count change, update Parameter
- memcpy(dst->wmm_param, src->wmm_param, IEEE80211_AC_PRAM_LEN);
- }
-*/
- if (src->wmm_param[0].ac_aci_acm_aifsn || \
- src->wmm_param[1].ac_aci_acm_aifsn || \
- src->wmm_param[2].ac_aci_acm_aifsn || \
- src->wmm_param[3].ac_aci_acm_aifsn) {
- memcpy(dst->wmm_param, src->wmm_param, WME_AC_PRAM_LEN);
- }
- dst->QoS_Enable = src->QoS_Enable;
-#else
- dst->QoS_Enable = 1;//for Rtl8187 simulation
-#endif
- dst->SignalStrength = src->SignalStrength;
- dst->Turbo_Enable = src->Turbo_Enable;
- dst->CountryIeLen = src->CountryIeLen;
- memcpy(dst->CountryIeBuf, src->CountryIeBuf, src->CountryIeLen);
-}
-
-
-inline void
-ieee80211_process_probe_response(struct ieee80211_device *ieee,
- struct ieee80211_probe_response *beacon,
- struct ieee80211_rx_stats *stats)
-{
- struct ieee80211_network network;
- struct ieee80211_network *target;
- struct ieee80211_network *oldest = NULL;
-#ifdef CONFIG_IEEE80211_DEBUG
- struct ieee80211_info_element *info_element = &beacon->info_element;
-#endif
- unsigned long flags;
- short renew;
- u8 wmm_info;
- u8 is_beacon = (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == IEEE80211_STYPE_BEACON) ? 1 : 0; //YJ,add,080819,for hidden ap
-
- memset(&network, 0, sizeof(struct ieee80211_network));
-
- IEEE80211_DEBUG_SCAN(
- "'%s' (%pM): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
- escape_essid(info_element->data, info_element->len),
- beacon->header.addr3,
- (beacon->capability & (1<<0xf)) ? '1' : '0',
- (beacon->capability & (1<<0xe)) ? '1' : '0',
- (beacon->capability & (1<<0xd)) ? '1' : '0',
- (beacon->capability & (1<<0xc)) ? '1' : '0',
- (beacon->capability & (1<<0xb)) ? '1' : '0',
- (beacon->capability & (1<<0xa)) ? '1' : '0',
- (beacon->capability & (1<<0x9)) ? '1' : '0',
- (beacon->capability & (1<<0x8)) ? '1' : '0',
- (beacon->capability & (1<<0x7)) ? '1' : '0',
- (beacon->capability & (1<<0x6)) ? '1' : '0',
- (beacon->capability & (1<<0x5)) ? '1' : '0',
- (beacon->capability & (1<<0x4)) ? '1' : '0',
- (beacon->capability & (1<<0x3)) ? '1' : '0',
- (beacon->capability & (1<<0x2)) ? '1' : '0',
- (beacon->capability & (1<<0x1)) ? '1' : '0',
- (beacon->capability & (1<<0x0)) ? '1' : '0');
-
- if (ieee80211_network_init(ieee, beacon, &network, stats)) {
- IEEE80211_DEBUG_SCAN("Dropped '%s' (%pM) via %s.\n",
- escape_essid(info_element->data,
- info_element->len),
- beacon->header.addr3,
- WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
- IEEE80211_STYPE_PROBE_RESP ?
- "PROBE RESPONSE" : "BEACON");
- return;
- }
-
- // For Asus EeePc request,
- // (1) if wireless adapter receive get any 802.11d country code in AP beacon,
- // wireless adapter should follow the country code.
- // (2) If there is no any country code in beacon,
- // then wireless adapter should do active scan from ch1~11 and
- // passive scan from ch12~14
- if (ieee->bGlobalDomain) {
- if (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == IEEE80211_STYPE_PROBE_RESP) {
- // Case 1: Country code
- if (IS_COUNTRY_IE_VALID(ieee)) {
- if (!IsLegalChannel(ieee, network.channel)) {
- printk("GetScanInfo(): For Country code, filter probe response at channel(%d).\n", network.channel);
- return;
- }
- }
- // Case 2: No any country code.
- else {
- // Filter over channel ch12~14
- if (network.channel > 11) {
- printk("GetScanInfo(): For Global Domain, filter probe response at channel(%d).\n", network.channel);
- return;
- }
- }
- } else {
- // Case 1: Country code
- if (IS_COUNTRY_IE_VALID(ieee)) {
- if (!IsLegalChannel(ieee, network.channel)) {
- printk("GetScanInfo(): For Country code, filter beacon at channel(%d).\n", network.channel);
- return;
- }
- }
- // Case 2: No any country code.
- else {
- // Filter over channel ch12~14
- if (network.channel > 14) {
- printk("GetScanInfo(): For Global Domain, filter beacon at channel(%d).\n", network.channel);
- return;
- }
- }
- }
- }
- /* The network parsed correctly -- so now we scan our known networks
- * to see if we can find it in our list.
- *
- * NOTE: This search is definitely not optimized. Once its doing
- * the "right thing" we'll optimize it for efficiency if
- * necessary */
-
- /* Search for this entry in the list and update it if it is
- * already there. */
-
- spin_lock_irqsave(&ieee->lock, flags);
-
- if (is_same_network(&ieee->current_network, &network, ieee)) {
- wmm_info = ieee->current_network.wmm_info;
- //YJ,add,080819,for hidden ap
- if (is_beacon == 0)
- network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & ieee->current_network.flags);
- else if (ieee->state == IEEE80211_LINKED)
- ieee->NumRxBcnInPeriod++;
- //YJ,add,080819,for hidden ap,end
- //printk("====>network.ssid=%s cur_ssid=%s\n", network.ssid, ieee->current_network.ssid);
- update_network(&ieee->current_network, &network);
- }
-
- list_for_each_entry(target, &ieee->network_list, list) {
- if (is_same_network(target, &network, ieee))
- break;
- if ((oldest == NULL) ||
- (target->last_scanned < oldest->last_scanned))
- oldest = target;
- }
-
- /* If we didn't find a match, then get a new network slot to initialize
- * with this beacon's information */
- if (&target->list == &ieee->network_list) {
- if (list_empty(&ieee->network_free_list)) {
- /* If there are no more slots, expire the oldest */
- list_del(&oldest->list);
- target = oldest;
- IEEE80211_DEBUG_SCAN("Expired '%s' (%pM) from "
- "network list.\n",
- escape_essid(target->ssid,
- target->ssid_len),
- target->bssid);
- } else {
- /* Otherwise just pull from the free list */
- target = list_entry(ieee->network_free_list.next,
- struct ieee80211_network, list);
- list_del(ieee->network_free_list.next);
- }
-
-
-#ifdef CONFIG_IEEE80211_DEBUG
- IEEE80211_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n",
- escape_essid(network.ssid,
- network.ssid_len),
- network.bssid,
- WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
- IEEE80211_STYPE_PROBE_RESP ?
- "PROBE RESPONSE" : "BEACON");
-#endif
-
- memcpy(target, &network, sizeof(*target));
- list_add_tail(&target->list, &ieee->network_list);
- } else {
- IEEE80211_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n",
- escape_essid(target->ssid,
- target->ssid_len),
- target->bssid,
- WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
- IEEE80211_STYPE_PROBE_RESP ?
- "PROBE RESPONSE" : "BEACON");
-
- /* we have an entry and we are going to update it. But this entry may
- * be already expired. In this case we do the same as we found a new
- * net and call the new_net handler
- */
- renew = !time_after(target->last_scanned + ieee->scan_age, jiffies);
- //YJ,add,080819,for hidden ap
- if (is_beacon == 0)
- network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & target->flags);
- //if(strncmp(network.ssid, "linksys-c",9) == 0)
- // printk("====>2 network.ssid=%s FLAG=%d target.ssid=%s FLAG=%d\n", network.ssid, network.flags, target->ssid, target->flags);
- if (((network.flags & NETWORK_EMPTY_ESSID) == NETWORK_EMPTY_ESSID) \
- && (((network.ssid_len > 0) && (strncmp(target->ssid, network.ssid, network.ssid_len)))\
- || ((ieee->current_network.ssid_len == network.ssid_len) && (strncmp(ieee->current_network.ssid, network.ssid, network.ssid_len) == 0) && (ieee->state == IEEE80211_NOLINK))))
- renew = 1;
- //YJ,add,080819,for hidden ap,end
- update_network(target, &network);
- }
-
- spin_unlock_irqrestore(&ieee->lock, flags);
-}
-
-void ieee80211_rx_mgt(struct ieee80211_device *ieee,
- struct ieee80211_hdr_4addr *header,
- struct ieee80211_rx_stats *stats)
-{
- switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
-
- case IEEE80211_STYPE_BEACON:
- IEEE80211_DEBUG_MGMT("received BEACON (%d)\n",
- WLAN_FC_GET_STYPE(header->frame_ctl));
- IEEE80211_DEBUG_SCAN("Beacon\n");
- ieee80211_process_probe_response(
- ieee, (struct ieee80211_probe_response *)header, stats);
- break;
-
- case IEEE80211_STYPE_PROBE_RESP:
- IEEE80211_DEBUG_MGMT("received PROBE RESPONSE (%d)\n",
- WLAN_FC_GET_STYPE(header->frame_ctl));
- IEEE80211_DEBUG_SCAN("Probe response\n");
- ieee80211_process_probe_response(
- ieee, (struct ieee80211_probe_response *)header, stats);
- break;
- }
-}
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
deleted file mode 100644
index 03eb164798cd..000000000000
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
+++ /dev/null
@@ -1,2711 +0,0 @@
-/* IEEE 802.11 SoftMAC layer
- * Copyright (c) 2005 Andrea Merello <andrea.merello@gmail.com>
- *
- * Mostly extracted from the rtl8180-sa2400 driver for the
- * in-kernel generic ieee802.11 stack.
- *
- * Few lines might be stolen from other part of the ieee80211
- * stack. Copyright who own it's copyright
- *
- * WPA code stolen from the ipw2200 driver.
- * Copyright who own it's copyright.
- *
- * released under the GPL
- */
-
-#include "ieee80211.h"
-
-#include <linux/random.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/uaccess.h>
-#include <linux/etherdevice.h>
-
-#include "dot11d.h"
-
-short ieee80211_is_54g(const struct ieee80211_network *net)
-{
- return (net->rates_ex_len > 0) || (net->rates_len > 4);
-}
-
-short ieee80211_is_shortslot(const struct ieee80211_network *net)
-{
- return net->capability & WLAN_CAPABILITY_SHORT_SLOT;
-}
-
-/* returns the total length needed for placing the RATE MFIE
- * tag and the EXTENDED RATE MFIE tag if needed.
- * It encludes two bytes per tag for the tag itself and its len
- */
-static unsigned int ieee80211_MFIE_rate_len(struct ieee80211_device *ieee)
-{
- unsigned int rate_len = 0;
-
- if (ieee->modulation & IEEE80211_CCK_MODULATION)
- rate_len = IEEE80211_CCK_RATE_LEN + 2;
-
- if (ieee->modulation & IEEE80211_OFDM_MODULATION)
-
- rate_len += IEEE80211_OFDM_RATE_LEN + 2;
-
- return rate_len;
-}
-
-/* place the MFIE rate, tag to the memory (double) poised.
- * Then it updates the pointer so that it points after the new MFIE tag added.
- */
-static void ieee80211_MFIE_Brate(struct ieee80211_device *ieee, u8 **tag_p)
-{
- u8 *tag = *tag_p;
-
- if (ieee->modulation & IEEE80211_CCK_MODULATION) {
- *tag++ = MFIE_TYPE_RATES;
- *tag++ = 4;
- *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
- *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
- *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
- *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
- }
-
- /* We may add an option for custom rates that specific HW might support */
- *tag_p = tag;
-}
-
-static void ieee80211_MFIE_Grate(struct ieee80211_device *ieee, u8 **tag_p)
-{
- u8 *tag = *tag_p;
-
- if (ieee->modulation & IEEE80211_OFDM_MODULATION) {
- *tag++ = MFIE_TYPE_RATES_EX;
- *tag++ = 8;
- *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
- *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
- *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
- *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
- *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
- *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
- *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
- *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
-
- }
- /* We may add an option for custom rates that specific HW might support */
- *tag_p = tag;
-}
-
-static void ieee80211_WMM_Info(struct ieee80211_device *ieee, u8 **tag_p)
-{
- u8 *tag = *tag_p;
-
- *tag++ = MFIE_TYPE_GENERIC; /* 0 */
- *tag++ = 7;
- *tag++ = 0x00;
- *tag++ = 0x50;
- *tag++ = 0xf2;
- *tag++ = 0x02; /* 5 */
- *tag++ = 0x00;
- *tag++ = 0x01;
-#ifdef SUPPORT_USPD
- if (ieee->current_network.wmm_info & 0x80)
- *tag++ = 0x0f|MAX_SP_Len;
- else
- *tag++ = MAX_SP_Len;
-#else
- *tag++ = MAX_SP_Len;
-#endif
- *tag_p = tag;
-}
-
-static void ieee80211_TURBO_Info(struct ieee80211_device *ieee, u8 **tag_p)
-{
- u8 *tag = *tag_p;
- *tag++ = MFIE_TYPE_GENERIC; /* 0 */
- *tag++ = 7;
- *tag++ = 0x00;
- *tag++ = 0xe0;
- *tag++ = 0x4c;
- *tag++ = 0x01; /* 5 */
- *tag++ = 0x02;
- *tag++ = 0x11;
- *tag++ = 0x00;
- *tag_p = tag;
- printk(KERN_ALERT "This is enable turbo mode IE process\n");
-}
-
-static void enqueue_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb)
-{
- int nh;
- nh = (ieee->mgmt_queue_head + 1) % MGMT_QUEUE_NUM;
-
- ieee->mgmt_queue_head = nh;
- ieee->mgmt_queue_ring[nh] = skb;
-}
-
-static struct sk_buff *dequeue_mgmt(struct ieee80211_device *ieee)
-{
- struct sk_buff *ret;
-
- if (ieee->mgmt_queue_tail == ieee->mgmt_queue_head)
- return NULL;
-
- ret = ieee->mgmt_queue_ring[ieee->mgmt_queue_tail];
-
- ieee->mgmt_queue_tail =
- (ieee->mgmt_queue_tail + 1) % MGMT_QUEUE_NUM;
-
- return ret;
-}
-
-static void init_mgmt_queue(struct ieee80211_device *ieee)
-{
- ieee->mgmt_queue_tail = ieee->mgmt_queue_head = 0;
-}
-
-void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl);
-
-inline void softmac_mgmt_xmit(struct sk_buff *skb,
- struct ieee80211_device *ieee)
-{
- unsigned long flags;
- short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
- struct ieee80211_hdr_3addr *header =
- (struct ieee80211_hdr_3addr *) skb->data;
-
- spin_lock_irqsave(&ieee->lock, flags);
-
- /* called with 2nd param 0, no mgmt lock required */
- ieee80211_sta_wakeup(ieee, 0);
-
- if (single) {
- if (ieee->queue_stop) {
- enqueue_mgmt(ieee, skb);
- } else {
- header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0]<<4);
-
- if (ieee->seq_ctrl[0] == 0xFFF)
- ieee->seq_ctrl[0] = 0;
- else
- ieee->seq_ctrl[0]++;
-
- /* avoid watchdog triggers */
- ieee->dev->trans_start = jiffies;
- ieee->softmac_data_hard_start_xmit(skb, ieee->dev, ieee->basic_rate);
- }
-
- spin_unlock_irqrestore(&ieee->lock, flags);
- } else {
- spin_unlock_irqrestore(&ieee->lock, flags);
- spin_lock_irqsave(&ieee->mgmt_tx_lock, flags);
-
- header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
-
- if (ieee->seq_ctrl[0] == 0xFFF)
- ieee->seq_ctrl[0] = 0;
- else
- ieee->seq_ctrl[0]++;
-
- /* avoid watchdog triggers */
- ieee->dev->trans_start = jiffies;
- ieee->softmac_hard_start_xmit(skb, ieee->dev);
-
- spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags);
- }
-}
-
-inline void softmac_ps_mgmt_xmit(struct sk_buff *skb,
- struct ieee80211_device *ieee)
-{
- short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
- struct ieee80211_hdr_3addr *header =
- (struct ieee80211_hdr_3addr *) skb->data;
-
- if (single) {
- header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
-
- if (ieee->seq_ctrl[0] == 0xFFF)
- ieee->seq_ctrl[0] = 0;
- else
- ieee->seq_ctrl[0]++;
-
- /* avoid watchdog triggers */
- ieee->dev->trans_start = jiffies;
- ieee->softmac_data_hard_start_xmit(skb, ieee->dev, ieee->basic_rate);
- } else {
- header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
-
- if (ieee->seq_ctrl[0] == 0xFFF)
- ieee->seq_ctrl[0] = 0;
- else
- ieee->seq_ctrl[0]++;
-
- /* avoid watchdog triggers */
- ieee->dev->trans_start = jiffies;
- ieee->softmac_hard_start_xmit(skb, ieee->dev);
- }
-}
-
-inline struct sk_buff *
-ieee80211_disassociate_skb(struct ieee80211_network *beacon,
- struct ieee80211_device *ieee, u8 asRsn)
-{
- struct sk_buff *skb;
- struct ieee80211_disassoc_frame *disass;
-
- skb = dev_alloc_skb(sizeof(struct ieee80211_disassoc_frame));
- if (!skb)
- return NULL;
-
- disass = (struct ieee80211_disassoc_frame *) skb_put(skb, sizeof(struct ieee80211_disassoc_frame));
- disass->header.frame_control = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
- disass->header.duration_id = 0;
-
- memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN);
- memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
- memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN);
-
- disass->reasoncode = asRsn;
- return skb;
-}
-
-void SendDisassociation(struct ieee80211_device *ieee, u8 *asSta, u8 asRsn)
-{
- struct ieee80211_network *beacon = &ieee->current_network;
- struct sk_buff *skb;
- skb = ieee80211_disassociate_skb(beacon, ieee, asRsn);
- if (skb)
- softmac_mgmt_xmit(skb, ieee);
-}
-
-inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee)
-{
- unsigned int len, rate_len;
- u8 *tag;
- struct sk_buff *skb;
- struct ieee80211_probe_request *req;
-
- len = ieee->current_network.ssid_len;
-
- rate_len = ieee80211_MFIE_rate_len(ieee);
-
- skb = dev_alloc_skb(sizeof(struct ieee80211_probe_request) +
- 2 + len + rate_len);
- if (!skb)
- return NULL;
-
- req = (struct ieee80211_probe_request *) skb_put(skb, sizeof(struct ieee80211_probe_request));
- req->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
- req->header.duration_id = 0; /* FIXME: is this OK ? */
-
- memset(req->header.addr1, 0xff, ETH_ALEN);
- memcpy(req->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
- memset(req->header.addr3, 0xff, ETH_ALEN);
-
- tag = (u8 *) skb_put(skb, len + 2 + rate_len);
-
- *tag++ = MFIE_TYPE_SSID;
- *tag++ = len;
- memcpy(tag, ieee->current_network.ssid, len);
- tag += len;
- ieee80211_MFIE_Brate(ieee, &tag);
- ieee80211_MFIE_Grate(ieee, &tag);
-
- return skb;
-}
-
-struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee);
-
-static void ieee80211_send_beacon(struct ieee80211_device *ieee)
-{
- struct sk_buff *skb;
-
- skb = ieee80211_get_beacon_(ieee);
-
- if (skb) {
- softmac_mgmt_xmit(skb, ieee);
- ieee->softmac_stats.tx_beacons++;
- dev_kfree_skb_any(skb);
- }
-
- ieee->beacon_timer.expires = jiffies +
- (MSECS(ieee->current_network.beacon_interval - 5));
-
- if (ieee->beacon_txing)
- add_timer(&ieee->beacon_timer);
-}
-
-
-static void ieee80211_send_beacon_cb(unsigned long _ieee)
-{
- struct ieee80211_device *ieee =
- (struct ieee80211_device *) _ieee;
- unsigned long flags;
-
- spin_lock_irqsave(&ieee->beacon_lock, flags);
- ieee80211_send_beacon(ieee);
- spin_unlock_irqrestore(&ieee->beacon_lock, flags);
-}
-
-static void ieee80211_send_probe(struct ieee80211_device *ieee)
-{
- struct sk_buff *skb;
-
- skb = ieee80211_probe_req(ieee);
- if (skb) {
- softmac_mgmt_xmit(skb, ieee);
- ieee->softmac_stats.tx_probe_rq++;
- }
-}
-
-static void ieee80211_send_probe_requests(struct ieee80211_device *ieee)
-{
- if (ieee->active_scan && (ieee->softmac_features & IEEE_SOFTMAC_PROBERQ)) {
- ieee80211_send_probe(ieee);
- ieee80211_send_probe(ieee);
- }
-}
-
-/* this performs syncro scan blocking the caller until all channels
- * in the allowed channel map has been checked.
- */
-static void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee)
-{
- short ch = 0;
- u8 channel_map[MAX_CHANNEL_NUMBER+1];
- memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
- down(&ieee->scan_sem);
-
- while (1) {
- do {
- ch++;
- if (ch > MAX_CHANNEL_NUMBER)
- goto out; /* scan completed */
-
- } while (!channel_map[ch]);
- /* this function can be called in two situations
- * 1- We have switched to ad-hoc mode and we are
- * performing a complete syncro scan before conclude
- * there are no interesting cell and to create a
- * new one. In this case the link state is
- * IEEE80211_NOLINK until we found an interesting cell.
- * If so the ieee8021_new_net, called by the RX path
- * will set the state to IEEE80211_LINKED, so we stop
- * scanning
- * 2- We are linked and the root uses run iwlist scan.
- * So we switch to IEEE80211_LINKED_SCANNING to remember
- * that we are still logically linked (not interested in
- * new network events, despite for updating the net list,
- * but we are temporarily 'unlinked' as the driver shall
- * not filter RX frames and the channel is changing.
- * So the only situation in witch are interested is to check
- * if the state become LINKED because of the #1 situation
- */
-
- if (ieee->state == IEEE80211_LINKED)
- goto out;
-
- ieee->set_chan(ieee->dev, ch);
- if (channel_map[ch] == 1)
- ieee80211_send_probe_requests(ieee);
-
- /* this prevent excessive time wait when we
- * need to wait for a syncro scan to end..
- */
- if (ieee->sync_scan_hurryup)
- goto out;
-
- msleep_interruptible_rtl(IEEE80211_SOFTMAC_SCAN_TIME);
- }
-out:
- ieee->sync_scan_hurryup = 0;
- up(&ieee->scan_sem);
- if (IS_DOT11D_ENABLE(ieee))
- DOT11D_ScanComplete(ieee);
-}
-
-void ieee80211_softmac_ips_scan_syncro(struct ieee80211_device *ieee)
-{
- int ch;
- unsigned int watch_dog = 0;
- u8 channel_map[MAX_CHANNEL_NUMBER+1];
- memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
- down(&ieee->scan_sem);
- ch = ieee->current_network.channel;
-
- while (1) {
- /* this function can be called in two situations
- * 1- We have switched to ad-hoc mode and we are
- * performing a complete syncro scan before conclude
- * there are no interesting cell and to create a
- * new one. In this case the link state is
- * IEEE80211_NOLINK until we found an interesting cell.
- * If so the ieee8021_new_net, called by the RX path
- * will set the state to IEEE80211_LINKED, so we stop
- * scanning
- * 2- We are linked and the root uses run iwlist scan.
- * So we switch to IEEE80211_LINKED_SCANNING to remember
- * that we are still logically linked (not interested in
- * new network events, despite for updating the net list,
- * but we are temporarily 'unlinked' as the driver shall
- * not filter RX frames and the channel is changing.
- * So the only situation in witch are interested is to check
- * if the state become LINKED because of the #1 situation
- */
- if (ieee->state == IEEE80211_LINKED)
- goto out;
-
- if (channel_map[ieee->current_network.channel] > 0)
- ieee->set_chan(ieee->dev, ieee->current_network.channel);
-
- if (channel_map[ieee->current_network.channel] == 1)
- ieee80211_send_probe_requests(ieee);
-
- msleep_interruptible_rtl(IEEE80211_SOFTMAC_SCAN_TIME);
-
- do {
- if (watch_dog++ >= MAX_CHANNEL_NUMBER)
- goto out; /* scan completed */
-
- ieee->current_network.channel = (ieee->current_network.channel + 1)%MAX_CHANNEL_NUMBER;
- } while (!channel_map[ieee->current_network.channel]);
- }
-out:
- ieee->actscanning = false;
- up(&ieee->scan_sem);
- if (IS_DOT11D_ENABLE(ieee))
- DOT11D_ScanComplete(ieee);
-}
-
-static void ieee80211_softmac_scan_wq(struct work_struct *work)
-{
- struct delayed_work *dwork = to_delayed_work(work);
- struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, softmac_scan_wq);
- static short watchdog;
- u8 channel_map[MAX_CHANNEL_NUMBER+1];
- memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
- down(&ieee->scan_sem);
-
- do {
- ieee->current_network.channel =
- (ieee->current_network.channel + 1) % MAX_CHANNEL_NUMBER;
- if (watchdog++ > MAX_CHANNEL_NUMBER)
- goto out; /* no good chans */
- } while (!channel_map[ieee->current_network.channel]);
-
- if (ieee->scanning == 0) {
- printk("error out, scanning = 0\n");
- goto out;
- }
- ieee->set_chan(ieee->dev, ieee->current_network.channel);
- if (channel_map[ieee->current_network.channel] == 1)
- ieee80211_send_probe_requests(ieee);
-
- queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, IEEE80211_SOFTMAC_SCAN_TIME);
- up(&ieee->scan_sem);
- return;
-out:
- ieee->actscanning = false;
- watchdog = 0;
- ieee->scanning = 0;
- up(&ieee->scan_sem);
-
- if (IS_DOT11D_ENABLE(ieee))
- DOT11D_ScanComplete(ieee);
- return;
-}
-
-static void ieee80211_beacons_start(struct ieee80211_device *ieee)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&ieee->beacon_lock, flags);
-
- ieee->beacon_txing = 1;
- ieee80211_send_beacon(ieee);
-
- spin_unlock_irqrestore(&ieee->beacon_lock, flags);
-}
-
-static void ieee80211_beacons_stop(struct ieee80211_device *ieee)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&ieee->beacon_lock, flags);
-
- ieee->beacon_txing = 0;
- del_timer_sync(&ieee->beacon_timer);
-
- spin_unlock_irqrestore(&ieee->beacon_lock, flags);
-}
-
-void ieee80211_stop_send_beacons(struct ieee80211_device *ieee)
-{
- if (ieee->stop_send_beacons)
- ieee->stop_send_beacons(ieee->dev);
- if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
- ieee80211_beacons_stop(ieee);
-}
-
-void ieee80211_start_send_beacons(struct ieee80211_device *ieee)
-{
- if (ieee->start_send_beacons)
- ieee->start_send_beacons(ieee->dev);
- if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
- ieee80211_beacons_start(ieee);
-}
-
-static void ieee80211_softmac_stop_scan(struct ieee80211_device *ieee)
-{
- down(&ieee->scan_sem);
-
- if (ieee->scanning == 1) {
- ieee->scanning = 0;
- cancel_delayed_work(&ieee->softmac_scan_wq);
- }
-
- up(&ieee->scan_sem);
-}
-
-void ieee80211_stop_scan(struct ieee80211_device *ieee)
-{
- if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
- ieee80211_softmac_stop_scan(ieee);
- else
- ieee->stop_scan(ieee->dev);
-}
-
-/* called with ieee->lock held */
-void ieee80211_rtl_start_scan(struct ieee80211_device *ieee)
-{
- if (IS_DOT11D_ENABLE(ieee)) {
- if (IS_COUNTRY_IE_VALID(ieee))
- RESET_CIE_WATCHDOG(ieee);
- }
-
- if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) {
- if (ieee->scanning == 0) {
- ieee->scanning = 1;
-#if 1
- queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, 0);
-#endif
- }
- }else
- ieee->start_scan(ieee->dev);
-}
-
-/* called with wx_sem held */
-void ieee80211_start_scan_syncro(struct ieee80211_device *ieee)
-{
- if (IS_DOT11D_ENABLE(ieee)) {
- if (IS_COUNTRY_IE_VALID(ieee))
- RESET_CIE_WATCHDOG(ieee);
- }
- ieee->sync_scan_hurryup = 0;
-
- if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
- ieee80211_softmac_scan_syncro(ieee);
- else
- ieee->scan_syncro(ieee->dev);
-}
-
-inline struct sk_buff *
-ieee80211_authentication_req(struct ieee80211_network *beacon,
- struct ieee80211_device *ieee, int challengelen)
-{
- struct sk_buff *skb;
- struct ieee80211_authentication *auth;
-
- skb = dev_alloc_skb(sizeof(struct ieee80211_authentication) + challengelen);
-
- if (!skb)
- return NULL;
-
- auth = (struct ieee80211_authentication *)
- skb_put(skb, sizeof(struct ieee80211_authentication));
-
- auth->header.frame_ctl = IEEE80211_STYPE_AUTH;
- if (challengelen)
- auth->header.frame_ctl |= IEEE80211_FCTL_WEP;
-
- auth->header.duration_id = 0x013a; /* FIXME */
-
- memcpy(auth->header.addr1, beacon->bssid, ETH_ALEN);
- memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
- memcpy(auth->header.addr3, beacon->bssid, ETH_ALEN);
-
- auth->algorithm = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
-
- auth->transaction = cpu_to_le16(ieee->associate_seq);
- ieee->associate_seq++;
-
- auth->status = cpu_to_le16(WLAN_STATUS_SUCCESS);
-
- return skb;
-}
-
-static struct sk_buff *ieee80211_probe_resp(struct ieee80211_device *ieee,
- u8 *dest)
-{
- u8 *tag;
- int beacon_size;
- struct ieee80211_probe_response *beacon_buf;
- struct sk_buff *skb;
- int encrypt;
- int atim_len, erp_len;
- struct ieee80211_crypt_data *crypt;
-
- char *ssid = ieee->current_network.ssid;
- int ssid_len = ieee->current_network.ssid_len;
- int rate_len = ieee->current_network.rates_len+2;
- int rate_ex_len = ieee->current_network.rates_ex_len;
- int wpa_ie_len = ieee->wpa_ie_len;
- if (rate_ex_len > 0)
- rate_ex_len += 2;
-
- if (ieee->current_network.capability & WLAN_CAPABILITY_IBSS)
- atim_len = 4;
- else
- atim_len = 0;
-
- if (ieee80211_is_54g(&ieee->current_network))
- erp_len = 3;
- else
- erp_len = 0;
-
- beacon_size = sizeof(struct ieee80211_probe_response)+
- ssid_len
- +3 /* channel */
- +rate_len
- +rate_ex_len
- +atim_len
- +wpa_ie_len
- +erp_len;
-
- skb = dev_alloc_skb(beacon_size);
-
- if (!skb)
- return NULL;
-
- beacon_buf = (struct ieee80211_probe_response *) skb_put(skb, beacon_size);
-
- memcpy(beacon_buf->header.addr1, dest, ETH_ALEN);
- memcpy(beacon_buf->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
- memcpy(beacon_buf->header.addr3, ieee->current_network.bssid, ETH_ALEN);
-
- beacon_buf->header.duration_id = 0; /* FIXME */
- beacon_buf->beacon_interval =
- cpu_to_le16(ieee->current_network.beacon_interval);
- beacon_buf->capability =
- cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_IBSS);
-
- if (ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT))
- beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
-
- crypt = ieee->crypt[ieee->tx_keyidx];
-
- encrypt = ieee->host_encrypt && crypt && crypt->ops &&
- ((0 == strcmp(crypt->ops->name, "WEP")) || wpa_ie_len);
-
- if (encrypt)
- beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
-
-
- beacon_buf->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP);
-
- beacon_buf->info_element.id = MFIE_TYPE_SSID;
- beacon_buf->info_element.len = ssid_len;
-
- tag = (u8 *) beacon_buf->info_element.data;
-
- memcpy(tag, ssid, ssid_len);
-
- tag += ssid_len;
-
- *(tag++) = MFIE_TYPE_RATES;
- *(tag++) = rate_len - 2;
- memcpy(tag, ieee->current_network.rates, rate_len-2);
- tag += rate_len - 2;
-
- *(tag++) = MFIE_TYPE_DS_SET;
- *(tag++) = 1;
- *(tag++) = ieee->current_network.channel;
-
- if (atim_len) {
- *(tag++) = MFIE_TYPE_IBSS_SET;
- *(tag++) = 2;
- *((u16 *)(tag)) = cpu_to_le16(ieee->current_network.atim_window);
- tag += 2;
- }
-
- if (erp_len) {
- *(tag++) = MFIE_TYPE_ERP;
- *(tag++) = 1;
- *(tag++) = 0;
- }
-
- if (rate_ex_len) {
- *(tag++) = MFIE_TYPE_RATES_EX;
- *(tag++) = rate_ex_len-2;
- memcpy(tag, ieee->current_network.rates_ex, rate_ex_len-2);
- tag += rate_ex_len - 2;
- }
-
- if (wpa_ie_len) {
- if (ieee->iw_mode == IW_MODE_ADHOC) {
- /* as Windows will set pairwise key same as the group
- * key which is not allowed in Linux, so set this for
- * IOT issue.
- */
- memcpy(&ieee->wpa_ie[14], &ieee->wpa_ie[8], 4);
- }
-
- memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
- }
- skb->dev = ieee->dev;
- return skb;
-}
-
-static struct sk_buff *ieee80211_assoc_resp(struct ieee80211_device *ieee,
- u8 *dest)
-{
- struct sk_buff *skb;
- u8 *tag;
-
- struct ieee80211_crypt_data *crypt;
- struct ieee80211_assoc_response_frame *assoc;
- short encrypt;
-
- unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
- int len = sizeof(struct ieee80211_assoc_response_frame) + rate_len;
-
- skb = dev_alloc_skb(len);
-
- if (!skb)
- return NULL;
-
- assoc = (struct ieee80211_assoc_response_frame *)
- skb_put(skb, sizeof(struct ieee80211_assoc_response_frame));
-
- assoc->header.frame_control = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP);
- memcpy(assoc->header.addr1, dest, ETH_ALEN);
- memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
- memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
- assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ?
- WLAN_CAPABILITY_BSS : WLAN_CAPABILITY_IBSS);
-
- if (ieee->short_slot)
- assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
-
- if (ieee->host_encrypt)
- crypt = ieee->crypt[ieee->tx_keyidx];
- else
- crypt = NULL;
-
- encrypt = (crypt && crypt->ops);
-
- if (encrypt)
- assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
-
- assoc->status = 0;
- assoc->aid = cpu_to_le16(ieee->assoc_id);
- if (ieee->assoc_id == 0x2007)
- ieee->assoc_id = 0;
- else
- ieee->assoc_id++;
-
- tag = (u8 *) skb_put(skb, rate_len);
-
- ieee80211_MFIE_Brate(ieee, &tag);
- ieee80211_MFIE_Grate(ieee, &tag);
-
- return skb;
-}
-
-static struct sk_buff *ieee80211_auth_resp(struct ieee80211_device *ieee,
- int status, u8 *dest)
-{
- struct sk_buff *skb;
- struct ieee80211_authentication *auth;
-
- skb = dev_alloc_skb(sizeof(struct ieee80211_authentication)+1);
-
- if (!skb)
- return NULL;
-
- skb->len = sizeof(struct ieee80211_authentication);
-
- auth = (struct ieee80211_authentication *)skb->data;
-
- auth->status = cpu_to_le16(status);
- auth->transaction = cpu_to_le16(2);
- auth->algorithm = cpu_to_le16(WLAN_AUTH_OPEN);
-
- memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
- memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
- memcpy(auth->header.addr1, dest, ETH_ALEN);
- auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH);
- return skb;
-}
-
-static struct sk_buff *ieee80211_null_func(struct ieee80211_device *ieee, short pwr)
-{
- struct sk_buff *skb;
- struct ieee80211_hdr_3addr *hdr;
-
- skb = dev_alloc_skb(sizeof(struct ieee80211_hdr_3addr));
-
- if (!skb)
- return NULL;
-
- hdr = (struct ieee80211_hdr_3addr *)skb_put(skb, sizeof(struct ieee80211_hdr_3addr));
-
- memcpy(hdr->addr1, ieee->current_network.bssid, ETH_ALEN);
- memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN);
- memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN);
-
- hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
- IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS |
- (pwr ? IEEE80211_FCTL_PM:0));
-
- return skb;
-}
-
-static void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8 *dest)
-{
- struct sk_buff *buf = ieee80211_assoc_resp(ieee, dest);
-
- if (buf) {
- softmac_mgmt_xmit(buf, ieee);
- dev_kfree_skb_any(buf);
- }
-}
-
-static void ieee80211_resp_to_auth(struct ieee80211_device *ieee, int s, u8 *dest)
-{
- struct sk_buff *buf = ieee80211_auth_resp(ieee, s, dest);
-
- if (buf) {
- softmac_mgmt_xmit(buf, ieee);
- dev_kfree_skb_any(buf);
- }
-}
-
-static void ieee80211_resp_to_probe(struct ieee80211_device *ieee, u8 *dest)
-{
- struct sk_buff *buf = ieee80211_probe_resp(ieee, dest);
-
- if (buf) {
- softmac_mgmt_xmit(buf, ieee);
- dev_kfree_skb_any(buf);
- }
-}
-
-inline struct sk_buff *
-ieee80211_association_req(struct ieee80211_network *beacon,
- struct ieee80211_device *ieee)
-{
- struct sk_buff *skb;
-
- struct ieee80211_assoc_request_frame *hdr;
- u8 *tag;
- unsigned int wpa_len = beacon->wpa_ie_len;
-#if 1
- /* for testing purpose */
- unsigned int rsn_len = beacon->rsn_ie_len;
-#endif
- unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
- unsigned int wmm_info_len = beacon->QoS_Enable?9:0;
- unsigned int turbo_info_len = beacon->Turbo_Enable?9:0;
-
- u8 encry_proto = ieee->wpax_type_notify & 0xff;
-
- int len = 0;
-
- /* [0] Notify type of encryption: WPA/WPA2
- * [1] pair wise type
- * [2] authen type
- */
- if (ieee->wpax_type_set) {
- if (IEEE_PROTO_WPA == encry_proto) {
- rsn_len = 0;
- } else if (IEEE_PROTO_RSN == encry_proto) {
- wpa_len = 0;
- }
- }
- len = sizeof(struct ieee80211_assoc_request_frame)+
- + beacon->ssid_len /* essid tagged val */
- + rate_len /* rates tagged val */
- + wpa_len
- + rsn_len
- + wmm_info_len
- + turbo_info_len;
-
- skb = dev_alloc_skb(len);
-
- if (!skb)
- return NULL;
-
- hdr = (struct ieee80211_assoc_request_frame *)
- skb_put(skb, sizeof(struct ieee80211_assoc_request_frame));
-
- hdr->header.frame_control = IEEE80211_STYPE_ASSOC_REQ;
- hdr->header.duration_id = 37; /* FIXME */
- memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN);
- memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
- memcpy(hdr->header.addr3, beacon->bssid, ETH_ALEN);
- memcpy(ieee->ap_mac_addr, beacon->bssid, ETH_ALEN); /* for HW security */
-
- hdr->capability = cpu_to_le16(WLAN_CAPABILITY_BSS);
- if (beacon->capability & WLAN_CAPABILITY_PRIVACY)
- hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
- if (beacon->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
- hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE);
-
- if (ieee->short_slot)
- hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
-
- hdr->listen_interval = 0xa; /* FIXME */
-
- hdr->info_element.id = MFIE_TYPE_SSID;
-
- hdr->info_element.len = beacon->ssid_len;
- tag = skb_put(skb, beacon->ssid_len);
- memcpy(tag, beacon->ssid, beacon->ssid_len);
-
- tag = skb_put(skb, rate_len);
-
- ieee80211_MFIE_Brate(ieee, &tag);
- ieee80211_MFIE_Grate(ieee, &tag);
-
- /* add rsn==0 condition for ap's mix security mode(wpa+wpa2)
- * choose AES encryption as default algorithm while using mixed mode.
- */
-
- tag = skb_put(skb, ieee->wpa_ie_len);
- memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
-
- tag = skb_put(skb, wmm_info_len);
- if (wmm_info_len)
- ieee80211_WMM_Info(ieee, &tag);
-
- tag = skb_put(skb, turbo_info_len);
- if (turbo_info_len)
- ieee80211_TURBO_Info(ieee, &tag);
-
- return skb;
-}
-
-void ieee80211_associate_abort(struct ieee80211_device *ieee)
-{
- unsigned long flags;
- spin_lock_irqsave(&ieee->lock, flags);
-
- ieee->associate_seq++;
-
- /* don't scan, and avoid to have the RX path possibly
- * try again to associate. Even do not react to AUTH or
- * ASSOC response. Just wait for the retry wq to be scheduled.
- * Here we will check if there are good nets to associate
- * with, so we retry or just get back to NO_LINK and scanning
- */
- if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING) {
- IEEE80211_DEBUG_MGMT("Authentication failed\n");
- ieee->softmac_stats.no_auth_rs++;
- } else {
- IEEE80211_DEBUG_MGMT("Association failed\n");
- ieee->softmac_stats.no_ass_rs++;
- }
-
- ieee->state = IEEE80211_ASSOCIATING_RETRY;
-
- queue_delayed_work(ieee->wq, &ieee->associate_retry_wq, IEEE80211_SOFTMAC_ASSOC_RETRY_TIME);
-
- spin_unlock_irqrestore(&ieee->lock, flags);
-}
-
-static void ieee80211_associate_abort_cb(unsigned long dev)
-{
- ieee80211_associate_abort((struct ieee80211_device *) dev);
-}
-
-static void ieee80211_associate_step1(struct ieee80211_device *ieee)
-{
- struct ieee80211_network *beacon = &ieee->current_network;
- struct sk_buff *skb;
-
- IEEE80211_DEBUG_MGMT("Stopping scan\n");
- ieee->softmac_stats.tx_auth_rq++;
- skb = ieee80211_authentication_req(beacon, ieee, 0);
- if (!skb) {
- ieee80211_associate_abort(ieee);
- } else {
- ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATING;
- IEEE80211_DEBUG_MGMT("Sending authentication request\n");
- softmac_mgmt_xmit(skb, ieee);
- /* BUGON when you try to add_timer twice, using mod_timer may
- * be better.
- */
- if (!timer_pending(&ieee->associate_timer)) {
- ieee->associate_timer.expires = jiffies + (HZ / 2);
- add_timer(&ieee->associate_timer);
- }
- /* If call dev_kfree_skb_any,a warning will ocur....
- * KERNEL: assertion (!atomic_read(&skb->users)) failed at
- * net/core/dev.c (1708)
- */
- }
-}
-
-static void ieee80211_rtl_auth_challenge(struct ieee80211_device *ieee, u8 *challenge,
- int chlen)
-{
- u8 *c;
- struct sk_buff *skb;
- struct ieee80211_network *beacon = &ieee->current_network;
- del_timer_sync(&ieee->associate_timer);
- ieee->associate_seq++;
- ieee->softmac_stats.tx_auth_rq++;
-
- skb = ieee80211_authentication_req(beacon, ieee, chlen+2);
- if (!skb)
- ieee80211_associate_abort(ieee);
- else {
- c = skb_put(skb, chlen+2);
- *(c++) = MFIE_TYPE_CHALLENGE;
- *(c++) = chlen;
- memcpy(c, challenge, chlen);
-
- IEEE80211_DEBUG_MGMT("Sending authentication challenge response\n");
-
- ieee80211_encrypt_fragment(ieee, skb, sizeof(struct ieee80211_hdr_3addr));
-
- softmac_mgmt_xmit(skb, ieee);
- if (!timer_pending(&ieee->associate_timer)) {
- ieee->associate_timer.expires = jiffies + (HZ / 2);
- add_timer(&ieee->associate_timer);
- }
- dev_kfree_skb_any(skb);
- }
- kfree(challenge);
-}
-
-static void ieee80211_associate_step2(struct ieee80211_device *ieee)
-{
- struct sk_buff *skb;
- struct ieee80211_network *beacon = &ieee->current_network;
-
- del_timer_sync(&ieee->associate_timer);
-
- IEEE80211_DEBUG_MGMT("Sending association request\n");
- ieee->softmac_stats.tx_ass_rq++;
- skb = ieee80211_association_req(beacon, ieee);
- if (!skb)
- ieee80211_associate_abort(ieee);
- else {
- softmac_mgmt_xmit(skb, ieee);
- if (!timer_pending(&ieee->associate_timer)) {
- ieee->associate_timer.expires = jiffies + (HZ / 2);
- add_timer(&ieee->associate_timer);
- }
- }
-}
-
-static void ieee80211_associate_complete_wq(struct work_struct *work)
-{
- struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_complete_wq);
-
- printk(KERN_INFO "Associated successfully\n");
- if (ieee80211_is_54g(&ieee->current_network) &&
- (ieee->modulation & IEEE80211_OFDM_MODULATION)) {
- ieee->rate = 540;
- printk(KERN_INFO"Using G rates\n");
- } else {
- ieee->rate = 110;
- printk(KERN_INFO"Using B rates\n");
- }
- ieee->link_change(ieee->dev);
- notify_wx_assoc_event(ieee);
- if (ieee->data_hard_resume)
- ieee->data_hard_resume(ieee->dev);
- netif_carrier_on(ieee->dev);
-}
-
-static void ieee80211_associate_complete(struct ieee80211_device *ieee)
-{
- del_timer_sync(&ieee->associate_timer);
-
- ieee->state = IEEE80211_LINKED;
- IEEE80211_DEBUG_MGMT("Successfully associated\n");
-
- queue_work(ieee->wq, &ieee->associate_complete_wq);
-}
-
-static void ieee80211_associate_procedure_wq(struct work_struct *work)
-{
- struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_procedure_wq);
-
- ieee->sync_scan_hurryup = 1;
- down(&ieee->wx_sem);
-
- if (ieee->data_hard_stop)
- ieee->data_hard_stop(ieee->dev);
-
- ieee80211_stop_scan(ieee);
- ieee->set_chan(ieee->dev, ieee->current_network.channel);
-
- ieee->associate_seq = 1;
- ieee80211_associate_step1(ieee);
-
- up(&ieee->wx_sem);
-}
-
-inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee,
- struct ieee80211_network *net)
-{
- u8 tmp_ssid[IW_ESSID_MAX_SIZE+1];
- int tmp_ssid_len = 0;
-
- short apset, ssidset, ssidbroad, apmatch, ssidmatch;
-
- /* we are interested in new new only if we are not associated
- * and we are not associating / authenticating
- */
- if (ieee->state != IEEE80211_NOLINK)
- return;
-
- if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability & WLAN_CAPABILITY_BSS))
- return;
-
- if ((ieee->iw_mode == IW_MODE_ADHOC) && !(net->capability & WLAN_CAPABILITY_IBSS))
- return;
-
- if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) {
- /* if the user specified the AP MAC, we need also the essid
- * This could be obtained by beacons or, if the network does not
- * broadcast it, it can be put manually.
- */
- apset = ieee->wap_set;
- ssidset = ieee->ssid_set;
- ssidbroad = !(net->ssid_len == 0 || net->ssid[0] == '\0');
- apmatch = (memcmp(ieee->current_network.bssid, net->bssid, ETH_ALEN) == 0);
-
- if (ieee->current_network.ssid_len != net->ssid_len)
- ssidmatch = 0;
- else
- ssidmatch = (0 == strncmp(ieee->current_network.ssid, net->ssid, net->ssid_len));
-
- /* if the user set the AP check if match.
- * if the network does not broadcast essid we check the user
- * supplied ANY essid
- * if the network does broadcast and the user does not set essid
- * it is OK
- * if the network does broadcast and the user did set essid
- * chech if essid match
- * (apset && apmatch && ((ssidset && ssidbroad && ssidmatch) ||
- * (ssidbroad && !ssidset) || (!ssidbroad && ssidset))) ||
- * if the ap is not set, check that the user set the bssid and
- * the network does broadcast and that those two bssid matches
- * (!apset && ssidset && ssidbroad && ssidmatch)
- */
- if ((apset && apmatch && ((ssidset && ssidbroad && ssidmatch) ||
- (ssidbroad && !ssidset) || (!ssidbroad && ssidset))) ||
- (!apset && ssidset && ssidbroad && ssidmatch)) {
- /* if the essid is hidden replace it with the
- * essid provided by the user.
- */
- if (!ssidbroad) {
- strncpy(tmp_ssid, ieee->current_network.ssid, IW_ESSID_MAX_SIZE);
- tmp_ssid_len = ieee->current_network.ssid_len;
- }
- memcpy(&ieee->current_network, net, sizeof(struct ieee80211_network));
-
- if (!ssidbroad) {
- strncpy(ieee->current_network.ssid, tmp_ssid, IW_ESSID_MAX_SIZE);
- ieee->current_network.ssid_len = tmp_ssid_len;
- }
- printk(KERN_INFO"Linking with %s: channel is %d\n", ieee->current_network.ssid, ieee->current_network.channel);
-
- if (ieee->iw_mode == IW_MODE_INFRA) {
- ieee->state = IEEE80211_ASSOCIATING;
- ieee->beinretry = false;
- queue_work(ieee->wq, &ieee->associate_procedure_wq);
- } else {
- if (ieee80211_is_54g(&ieee->current_network) &&
- (ieee->modulation & IEEE80211_OFDM_MODULATION)) {
- ieee->rate = 540;
- printk(KERN_INFO"Using G rates\n");
- } else {
- ieee->rate = 110;
- printk(KERN_INFO"Using B rates\n");
- }
- ieee->state = IEEE80211_LINKED;
- ieee->beinretry = false;
- }
- }
- }
-}
-
-void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee)
-{
- unsigned long flags;
- struct ieee80211_network *target;
-
- spin_lock_irqsave(&ieee->lock, flags);
- list_for_each_entry(target, &ieee->network_list, list) {
- /* if the state become different that NOLINK means
- * we had found what we are searching for
- */
- if (ieee->state != IEEE80211_NOLINK)
- break;
-
- if (ieee->scan_age == 0 || time_after(target->last_scanned + ieee->scan_age, jiffies))
- ieee80211_softmac_new_net(ieee, target);
- }
- spin_unlock_irqrestore(&ieee->lock, flags);
-}
-
-static inline u16 auth_parse(struct sk_buff *skb, u8 **challenge, int *chlen)
-{
- struct ieee80211_authentication *a;
- u8 *t;
- if (skb->len < (sizeof(struct ieee80211_authentication) - sizeof(struct ieee80211_info_element))) {
- IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
- return 0xcafe;
- }
- *challenge = NULL;
- a = (struct ieee80211_authentication *) skb->data;
- if (skb->len > (sizeof(struct ieee80211_authentication) + 3)) {
- t = skb->data + sizeof(struct ieee80211_authentication);
-
- if (*(t++) == MFIE_TYPE_CHALLENGE) {
- *chlen = *(t++);
- *challenge = kmemdup(t, *chlen, GFP_ATOMIC);
- if (!*challenge)
- return -ENOMEM;
- }
- }
- return cpu_to_le16(a->status);
-}
-
-static int auth_rq_parse(struct sk_buff *skb, u8 *dest)
-{
- struct ieee80211_authentication *a;
-
- if (skb->len < (sizeof(struct ieee80211_authentication) - sizeof(struct ieee80211_info_element))) {
- IEEE80211_DEBUG_MGMT("invalid len in auth request: %d\n", skb->len);
- return -1;
- }
- a = (struct ieee80211_authentication *) skb->data;
-
- memcpy(dest, a->header.addr2, ETH_ALEN);
-
- if (le16_to_cpu(a->algorithm) != WLAN_AUTH_OPEN)
- return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
-
- return WLAN_STATUS_SUCCESS;
-}
-
-static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb,
- u8 *src)
-{
- u8 *tag;
- u8 *skbend;
- u8 *ssid = NULL;
- u8 ssidlen = 0;
-
- struct ieee80211_hdr_3addr *header =
- (struct ieee80211_hdr_3addr *) skb->data;
-
- if (skb->len < sizeof(struct ieee80211_hdr_3addr))
- return -1; /* corrupted */
-
- memcpy(src, header->addr2, ETH_ALEN);
-
- skbend = (u8 *)skb->data + skb->len;
-
- tag = skb->data + sizeof(struct ieee80211_hdr_3addr);
-
- while (tag+1 < skbend) {
- if (*tag == 0) {
- ssid = tag+2;
- ssidlen = *(tag+1);
- break;
- }
- tag++; /* point to the len field */
- tag = tag + *(tag); /* point to the last data byte of the tag */
- tag++; /* point to the next tag */
- }
-
- if (ssidlen == 0)
- return 1;
-
- if (!ssid)
- return 1; /* ssid not found in tagged param */
-
- return (!strncmp(ssid, ieee->current_network.ssid, ssidlen));
-
-}
-
-static int assoc_rq_parse(struct sk_buff *skb, u8 *dest)
-{
- struct ieee80211_assoc_request_frame *a;
-
- if (skb->len < (sizeof(struct ieee80211_assoc_request_frame) -
- sizeof(struct ieee80211_info_element))) {
-
- IEEE80211_DEBUG_MGMT("invalid len in auth request:%d\n", skb->len);
- return -1;
- }
-
- a = (struct ieee80211_assoc_request_frame *) skb->data;
-
- memcpy(dest, a->header.addr2, ETH_ALEN);
-
- return 0;
-}
-
-static inline u16 assoc_parse(struct sk_buff *skb, int *aid)
-{
- struct ieee80211_assoc_response_frame *a;
- if (skb->len < sizeof(struct ieee80211_assoc_response_frame)) {
- IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
- return 0xcafe;
- }
-
- a = (struct ieee80211_assoc_response_frame *) skb->data;
- *aid = le16_to_cpu(a->aid) & 0x3fff;
- return le16_to_cpu(a->status);
-}
-
-static inline void ieee80211_rx_probe_rq(struct ieee80211_device *ieee,
- struct sk_buff *skb)
-{
- u8 dest[ETH_ALEN];
-
- ieee->softmac_stats.rx_probe_rq++;
- if (probe_rq_parse(ieee, skb, dest)) {
- ieee->softmac_stats.tx_probe_rs++;
- ieee80211_resp_to_probe(ieee, dest);
- }
-}
-
-inline void ieee80211_rx_auth_rq(struct ieee80211_device *ieee,
- struct sk_buff *skb)
-{
- u8 dest[ETH_ALEN];
- int status;
- ieee->softmac_stats.rx_auth_rq++;
-
- status = auth_rq_parse(skb, dest);
- if (status != -1)
- ieee80211_resp_to_auth(ieee, status, dest);
-}
-
-inline void
-ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
-{
-
- u8 dest[ETH_ALEN];
-
- ieee->softmac_stats.rx_ass_rq++;
- if (assoc_rq_parse(skb, dest) != -1)
- ieee80211_resp_to_assoc_rq(ieee, dest);
-
-
- printk(KERN_INFO"New client associated: %pM\n", dest);
-}
-
-void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr)
-{
- struct sk_buff *buf = ieee80211_null_func(ieee, pwr);
-
- if (buf)
- softmac_ps_mgmt_xmit(buf, ieee);
-}
-
-static short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h,
- u32 *time_l)
-{
- int timeout = 0;
-
- u8 dtim;
- dtim = ieee->current_network.dtim_data;
-
- if (!(dtim & IEEE80211_DTIM_VALID))
- return 0;
- else
- timeout = ieee->current_network.beacon_interval;
-
- ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID;
-
- if (dtim & ((IEEE80211_DTIM_UCAST | IEEE80211_DTIM_MBCAST) & ieee->ps))
- return 2;
-
- if (!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout)))
- return 0;
-
- if (!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout)))
- return 0;
-
- if ((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE) &&
- (ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
- return 0;
-
- if (time_l) {
- *time_l = ieee->current_network.last_dtim_sta_time[0]
- + MSECS((ieee->current_network.beacon_interval));
- }
-
- if (time_h) {
- *time_h = ieee->current_network.last_dtim_sta_time[1];
- if (time_l && *time_l < ieee->current_network.last_dtim_sta_time[0])
- *time_h += 1;
- }
-
- return 1;
-}
-
-static inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
-{
-
- u32 th, tl;
- short sleep;
-
- unsigned long flags, flags2;
-
- spin_lock_irqsave(&ieee->lock, flags);
-
- if ((ieee->ps == IEEE80211_PS_DISABLED ||
- ieee->iw_mode != IW_MODE_INFRA ||
- ieee->state != IEEE80211_LINKED)) {
-
- /* #warning CHECK_LOCK_HERE */
- spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
-
- ieee80211_sta_wakeup(ieee, 1);
-
- spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
- }
-
- sleep = ieee80211_sta_ps_sleep(ieee, &th, &tl);
- /* 2 wake, 1 sleep, 0 do nothing */
- if (sleep == 0)
- goto out;
-
- if (sleep == 1) {
- if (ieee->sta_sleep == 1)
- ieee->enter_sleep_state(ieee->dev, th, tl);
-
- else if (ieee->sta_sleep == 0) {
- spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
- if (ieee->ps_is_queue_empty(ieee->dev)) {
- ieee->sta_sleep = 2;
-
- ieee->ps_request_tx_ack(ieee->dev);
-
- ieee80211_sta_ps_send_null_frame(ieee, 1);
-
- ieee->ps_th = th;
- ieee->ps_tl = tl;
- }
- spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
- }
- } else if (sleep == 2) {
- /* #warning CHECK_LOCK_HERE */
- spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
-
- ieee80211_sta_wakeup(ieee, 1);
-
- spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
- }
-out:
- spin_unlock_irqrestore(&ieee->lock, flags);
-}
-
-void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
-{
- if (ieee->sta_sleep == 0) {
- if (nl) {
- ieee->ps_request_tx_ack(ieee->dev);
- ieee80211_sta_ps_send_null_frame(ieee, 0);
- }
- return;
- }
-
- if (ieee->sta_sleep == 1)
- ieee->sta_wake_up(ieee->dev);
-
- ieee->sta_sleep = 0;
-
- if (nl) {
- ieee->ps_request_tx_ack(ieee->dev);
- ieee80211_sta_ps_send_null_frame(ieee, 0);
- }
-}
-
-void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
-{
- unsigned long flags, flags2;
-
- spin_lock_irqsave(&ieee->lock, flags);
- if (ieee->sta_sleep == 2) {
- /* Null frame with PS bit set */
- if (success) {
- ieee->sta_sleep = 1;
- ieee->enter_sleep_state(ieee->dev, ieee->ps_th, ieee->ps_tl);
- }
- /* if the card report not success we can't be sure the AP
- * has not RXed so we can't assume the AP believe us awake
- */
- } else {
- if ((ieee->sta_sleep == 0) && !success) {
- spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
- ieee80211_sta_ps_send_null_frame(ieee, 0);
- spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
- }
- }
- spin_unlock_irqrestore(&ieee->lock, flags);
-}
-
-inline int ieee80211_rx_frame_softmac(struct ieee80211_device *ieee,
- struct sk_buff *skb,
- struct ieee80211_rx_stats *rx_stats,
- u16 type, u16 stype)
-{
- struct ieee80211_hdr_3addr *header = (struct ieee80211_hdr_3addr *) skb->data;
- u16 errcode;
- u8 *challenge = NULL;
- int chlen = 0;
- int aid = 0;
- struct ieee80211_assoc_response_frame *assoc_resp;
- struct ieee80211_info_element *info_element;
-
- if (!ieee->proto_started)
- return 0;
-
- if (ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED &&
- ieee->iw_mode == IW_MODE_INFRA &&
- ieee->state == IEEE80211_LINKED))
-
- tasklet_schedule(&ieee->ps_task);
-
- if (WLAN_FC_GET_STYPE(header->frame_control) != IEEE80211_STYPE_PROBE_RESP &&
- WLAN_FC_GET_STYPE(header->frame_control) != IEEE80211_STYPE_BEACON)
- ieee->last_rx_ps_time = jiffies;
-
- switch (WLAN_FC_GET_STYPE(header->frame_control)) {
- case IEEE80211_STYPE_ASSOC_RESP:
- case IEEE80211_STYPE_REASSOC_RESP:
- IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n",
- WLAN_FC_GET_STYPE(header->frame_ctl));
- if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
- ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED &&
- ieee->iw_mode == IW_MODE_INFRA) {
- errcode = assoc_parse(skb, &aid);
- if (0 == errcode) {
- u16 left;
-
- ieee->state = IEEE80211_LINKED;
- ieee->assoc_id = aid;
- ieee->softmac_stats.rx_ass_ok++;
- /* card type is 8187 */
- if (1 == rx_stats->nic_type)
- goto associate_complete;
-
- assoc_resp = (struct ieee80211_assoc_response_frame *)skb->data;
- info_element = &assoc_resp->info_element;
- left = skb->len - ((void *)info_element - (void *)assoc_resp);
-
- while (left >= sizeof(struct ieee80211_info_element_hdr)) {
- if (sizeof(struct ieee80211_info_element_hdr) + info_element->len > left) {
- printk(KERN_WARNING "[re]associate response error!");
- return 1;
- }
- switch (info_element->id) {
- case MFIE_TYPE_GENERIC:
- IEEE80211_DEBUG_SCAN("MFIE_TYPE_GENERIC: %d bytes\n", info_element->len);
- if (info_element->len >= 8 &&
- info_element->data[0] == 0x00 &&
- info_element->data[1] == 0x50 &&
- info_element->data[2] == 0xf2 &&
- info_element->data[3] == 0x02 &&
- info_element->data[4] == 0x01) {
- /* Not care about version at present.
- * WMM Parameter Element.
- */
- memcpy(ieee->current_network.wmm_param, (u8 *)(info_element->data\
- + 8), (info_element->len - 8));
-
- if (((ieee->current_network.wmm_info^info_element->data[6])& \
- 0x0f) || (!ieee->init_wmmparam_flag)) {
- /* refresh parameter element for current network
- * update the register parameter for hardware.
- */
- ieee->init_wmmparam_flag = 1;
- queue_work(ieee->wq, &ieee->wmm_param_update_wq);
- }
- /* update info_element for current network */
- ieee->current_network.wmm_info = info_element->data[6];
- }
- break;
- default:
- /* nothing to do at present!!! */
- break;
- }
-
- left -= sizeof(struct ieee80211_info_element_hdr) +
- info_element->len;
- info_element = (struct ieee80211_info_element *)
- &info_element->data[info_element->len];
- }
- /* legacy AP, reset the AC_xx_param register */
- if (!ieee->init_wmmparam_flag) {
- queue_work(ieee->wq, &ieee->wmm_param_update_wq);
- ieee->init_wmmparam_flag = 1; /* indicate AC_xx_param upated since last associate */
- }
-associate_complete:
- ieee80211_associate_complete(ieee);
- } else {
- ieee->softmac_stats.rx_ass_err++;
- IEEE80211_DEBUG_MGMT(
- "Association response status code 0x%x\n",
- errcode);
- ieee80211_associate_abort(ieee);
- }
- }
- break;
- case IEEE80211_STYPE_ASSOC_REQ:
- case IEEE80211_STYPE_REASSOC_REQ:
- if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
- ieee->iw_mode == IW_MODE_MASTER)
-
- ieee80211_rx_assoc_rq(ieee, skb);
- break;
- case IEEE80211_STYPE_AUTH:
- if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) {
- if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING &&
- ieee->iw_mode == IW_MODE_INFRA){
- IEEE80211_DEBUG_MGMT("Received authentication response");
-
- errcode = auth_parse(skb, &challenge, &chlen);
- if (0 == errcode) {
- if (ieee->open_wep || !challenge) {
- ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED;
- ieee->softmac_stats.rx_auth_rs_ok++;
-
- ieee80211_associate_step2(ieee);
- } else {
- ieee80211_rtl_auth_challenge(ieee, challenge, chlen);
- }
- } else {
- ieee->softmac_stats.rx_auth_rs_err++;
- IEEE80211_DEBUG_MGMT("Authentication response status code 0x%x", errcode);
- ieee80211_associate_abort(ieee);
- }
-
- } else if (ieee->iw_mode == IW_MODE_MASTER) {
- ieee80211_rx_auth_rq(ieee, skb);
- }
- }
- break;
- case IEEE80211_STYPE_PROBE_REQ:
- if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
- ((ieee->iw_mode == IW_MODE_ADHOC ||
- ieee->iw_mode == IW_MODE_MASTER) &&
- ieee->state == IEEE80211_LINKED))
-
- ieee80211_rx_probe_rq(ieee, skb);
- break;
- case IEEE80211_STYPE_DISASSOC:
- case IEEE80211_STYPE_DEAUTH:
- /* FIXME for now repeat all the association procedure
- * both for disassociation and deauthentication
- */
- if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
- (ieee->state == IEEE80211_LINKED) &&
- (ieee->iw_mode == IW_MODE_INFRA) &&
- (!memcmp(header->addr2, ieee->current_network.bssid, ETH_ALEN))) {
- ieee->state = IEEE80211_ASSOCIATING;
- ieee->softmac_stats.reassoc++;
-
- queue_work(ieee->wq, &ieee->associate_procedure_wq);
- }
- break;
- default:
- return -1;
- break;
- }
- return 0;
-}
-
-/* following are for a simpler TX queue management.
- * Instead of using netif_[stop/wake]_queue the driver
- * will uses these two function (plus a reset one), that
- * will internally uses the kernel netif_* and takes
- * care of the ieee802.11 fragmentation.
- * So the driver receives a fragment per time and might
- * call the stop function when it want without take care
- * to have enough room to TX an entire packet.
- * This might be useful if each fragment need it's own
- * descriptor, thus just keep a total free memory > than
- * the max fragmentation threshold is not enough.. If the
- * ieee802.11 stack passed a TXB struct then you needed
- * to keep N free descriptors where
- * N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD
- * In this way you need just one and the 802.11 stack
- * will take care of buffering fragments and pass them to
- * to the driver later, when it wakes the queue.
- */
-
-void ieee80211_softmac_xmit(struct ieee80211_txb *txb,
- struct ieee80211_device *ieee)
-{
- unsigned long flags;
- int i;
-
- spin_lock_irqsave(&ieee->lock, flags);
-
- /* called with 2nd parm 0, no tx mgmt lock required */
- ieee80211_sta_wakeup(ieee, 0);
-
- for (i = 0; i < txb->nr_frags; i++) {
- if (ieee->queue_stop) {
- ieee->tx_pending.txb = txb;
- ieee->tx_pending.frag = i;
- goto exit;
- } else {
- ieee->softmac_data_hard_start_xmit(
- txb->fragments[i],
- ieee->dev, ieee->rate);
- ieee->stats.tx_packets++;
- ieee->stats.tx_bytes += txb->fragments[i]->len;
- ieee->dev->trans_start = jiffies;
- }
- }
-
- ieee80211_txb_free(txb);
-
- exit:
- spin_unlock_irqrestore(&ieee->lock, flags);
-}
-
-/* called with ieee->lock acquired */
-static void ieee80211_resume_tx(struct ieee80211_device *ieee)
-{
- int i;
- for (i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) {
-
- if (ieee->queue_stop) {
- ieee->tx_pending.frag = i;
- return;
- } else {
- ieee->softmac_data_hard_start_xmit(
- ieee->tx_pending.txb->fragments[i],
- ieee->dev, ieee->rate);
- ieee->stats.tx_packets++;
- ieee->dev->trans_start = jiffies;
- }
- }
-
- ieee80211_txb_free(ieee->tx_pending.txb);
- ieee->tx_pending.txb = NULL;
-}
-
-void ieee80211_reset_queue(struct ieee80211_device *ieee)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&ieee->lock, flags);
- init_mgmt_queue(ieee);
- if (ieee->tx_pending.txb) {
- ieee80211_txb_free(ieee->tx_pending.txb);
- ieee->tx_pending.txb = NULL;
- }
- ieee->queue_stop = 0;
- spin_unlock_irqrestore(&ieee->lock, flags);
-}
-
-void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee)
-{
- unsigned long flags;
- struct sk_buff *skb;
- struct ieee80211_hdr_3addr *header;
-
- spin_lock_irqsave(&ieee->lock, flags);
- if (!ieee->queue_stop)
- goto exit;
-
- ieee->queue_stop = 0;
-
- if (ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE) {
- while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))) {
- header = (struct ieee80211_hdr_3addr *) skb->data;
-
- header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
-
- if (ieee->seq_ctrl[0] == 0xFFF)
- ieee->seq_ctrl[0] = 0;
- else
- ieee->seq_ctrl[0]++;
-
- ieee->softmac_data_hard_start_xmit(skb, ieee->dev, ieee->basic_rate);
- dev_kfree_skb_any(skb);
- }
- }
- if (!ieee->queue_stop && ieee->tx_pending.txb)
- ieee80211_resume_tx(ieee);
-
- if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)) {
- ieee->softmac_stats.swtxawake++;
- netif_wake_queue(ieee->dev);
- }
-exit:
- spin_unlock_irqrestore(&ieee->lock, flags);
-}
-
-void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee)
-{
- if (!netif_queue_stopped(ieee->dev)) {
- netif_stop_queue(ieee->dev);
- ieee->softmac_stats.swtxstop++;
- }
- ieee->queue_stop = 1;
-}
-
-inline void ieee80211_randomize_cell(struct ieee80211_device *ieee)
-{
- random_ether_addr(ieee->current_network.bssid);
-}
-
-/* called in user context only */
-void ieee80211_start_master_bss(struct ieee80211_device *ieee)
-{
- ieee->assoc_id = 1;
-
- if (ieee->current_network.ssid_len == 0) {
- strncpy(ieee->current_network.ssid,
- IEEE80211_DEFAULT_TX_ESSID,
- IW_ESSID_MAX_SIZE);
-
- ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
- ieee->ssid_set = 1;
- }
-
- memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN);
-
- ieee->set_chan(ieee->dev, ieee->current_network.channel);
- ieee->state = IEEE80211_LINKED;
- ieee->link_change(ieee->dev);
- notify_wx_assoc_event(ieee);
-
- if (ieee->data_hard_resume)
- ieee->data_hard_resume(ieee->dev);
-
- netif_carrier_on(ieee->dev);
-}
-
-static void ieee80211_start_monitor_mode(struct ieee80211_device *ieee)
-{
- if (ieee->raw_tx) {
-
- if (ieee->data_hard_resume)
- ieee->data_hard_resume(ieee->dev);
-
- netif_carrier_on(ieee->dev);
- }
-}
-
-static void ieee80211_start_ibss_wq(struct work_struct *work)
-{
- struct delayed_work *dwork = to_delayed_work(work);
- struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq);
-
- /* iwconfig mode ad-hoc will schedule this and return
- * on the other hand this will block further iwconfig SET
- * operations because of the wx_sem hold.
- * Anyway some most set operations set a flag to speed-up
- * (abort) this wq (when syncro scanning) before sleeping
- * on the semaphore
- */
-
- down(&ieee->wx_sem);
-
- if (ieee->current_network.ssid_len == 0) {
- strcpy(ieee->current_network.ssid, IEEE80211_DEFAULT_TX_ESSID);
- ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
- ieee->ssid_set = 1;
- }
-
- /* check if we have this cell in our network list */
- ieee80211_softmac_check_all_nets(ieee);
-
- if (ieee->state == IEEE80211_NOLINK)
- ieee->current_network.channel = 10;
- /* if not then the state is not linked. Maybe the user switched to
- * ad-hoc mode just after being in monitor mode, or just after
- * being very few time in managed mode (so the card have had no
- * time to scan all the chans..) or we have just run up the iface
- * after setting ad-hoc mode. So we have to give another try..
- * Here, in ibss mode, should be safe to do this without extra care
- * (in bss mode we had to make sure no-one tried to associate when
- * we had just checked the ieee->state and we was going to start the
- * scan) because in ibss mode the ieee80211_new_net function, when
- * finds a good net, just set the ieee->state to IEEE80211_LINKED,
- * so, at worst, we waste a bit of time to initiate an unneeded syncro
- * scan, that will stop at the first round because it sees the state
- * associated.
- */
- if (ieee->state == IEEE80211_NOLINK)
- ieee80211_start_scan_syncro(ieee);
-
- /* the network definitively is not here.. create a new cell */
- if (ieee->state == IEEE80211_NOLINK) {
- printk("creating new IBSS cell\n");
- if (!ieee->wap_set)
- ieee80211_randomize_cell(ieee);
-
- if (ieee->modulation & IEEE80211_CCK_MODULATION) {
- ieee->current_network.rates_len = 4;
-
- ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
- ieee->current_network.rates[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
- ieee->current_network.rates[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
- ieee->current_network.rates[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
-
- } else
- ieee->current_network.rates_len = 0;
-
- if (ieee->modulation & IEEE80211_OFDM_MODULATION) {
- ieee->current_network.rates_ex_len = 8;
-
- ieee->current_network.rates_ex[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
- ieee->current_network.rates_ex[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
- ieee->current_network.rates_ex[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
- ieee->current_network.rates_ex[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
- ieee->current_network.rates_ex[4] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
- ieee->current_network.rates_ex[5] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
- ieee->current_network.rates_ex[6] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
- ieee->current_network.rates_ex[7] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
-
- ieee->rate = 540;
- } else {
- ieee->current_network.rates_ex_len = 0;
- ieee->rate = 110;
- }
-
- /* By default, WMM function will be disabled in IBSS mode */
- ieee->current_network.QoS_Enable = 0;
-
- ieee->current_network.atim_window = 0;
- ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
- if (ieee->short_slot)
- ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT;
- }
-
- ieee->state = IEEE80211_LINKED;
- ieee->set_chan(ieee->dev, ieee->current_network.channel);
- ieee->link_change(ieee->dev);
-
- notify_wx_assoc_event(ieee);
-
- ieee80211_start_send_beacons(ieee);
- printk(KERN_WARNING "after sending beacon packet!\n");
-
- if (ieee->data_hard_resume)
- ieee->data_hard_resume(ieee->dev);
-
- netif_carrier_on(ieee->dev);
-
- up(&ieee->wx_sem);
-}
-
-inline void ieee80211_start_ibss(struct ieee80211_device *ieee)
-{
- queue_delayed_work(ieee->wq, &ieee->start_ibss_wq, 100);
-}
-
-/* this is called only in user context, with wx_sem held */
-void ieee80211_start_bss(struct ieee80211_device *ieee)
-{
- unsigned long flags;
- /* Ref: 802.11d 11.1.3.3
- * STA shall not start a BSS unless properly formed Beacon frame
- * including a Country IE.
- */
- if (IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee)) {
- if (!ieee->bGlobalDomain)
- return;
- }
- /* check if we have already found the net we are interested in (if any).
- * if not (we are disassociated and we are not
- * in associating / authenticating phase) start the background scanning.
- */
- ieee80211_softmac_check_all_nets(ieee);
-
- /* ensure no-one start an associating process (thus setting
- * the ieee->state to ieee80211_ASSOCIATING) while we
- * have just cheked it and we are going to enable scan.
- * The ieee80211_new_net function is always called with
- * lock held (from both ieee80211_softmac_check_all_nets and
- * the rx path), so we cannot be in the middle of such function
- */
- spin_lock_irqsave(&ieee->lock, flags);
-
- if (ieee->state == IEEE80211_NOLINK) {
- ieee->actscanning = true;
- ieee80211_rtl_start_scan(ieee);
- }
- spin_unlock_irqrestore(&ieee->lock, flags);
-}
-
-/* called only in userspace context */
-void ieee80211_disassociate(struct ieee80211_device *ieee)
-{
- netif_carrier_off(ieee->dev);
-
- if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)
- ieee80211_reset_queue(ieee);
-
- if (ieee->data_hard_stop)
- ieee->data_hard_stop(ieee->dev);
-
- if (IS_DOT11D_ENABLE(ieee))
- Dot11d_Reset(ieee);
-
- ieee->link_change(ieee->dev);
- if (ieee->state == IEEE80211_LINKED)
- notify_wx_assoc_event(ieee);
- ieee->state = IEEE80211_NOLINK;
-
-}
-static void ieee80211_associate_retry_wq(struct work_struct *work)
-{
- struct delayed_work *dwork = to_delayed_work(work);
- struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq);
- unsigned long flags;
- down(&ieee->wx_sem);
- if (!ieee->proto_started)
- goto exit;
- if (ieee->state != IEEE80211_ASSOCIATING_RETRY)
- goto exit;
- /* until we do not set the state to IEEE80211_NOLINK
- * there are no possibility to have someone else trying
- * to start an association procedure (we get here with
- * ieee->state = IEEE80211_ASSOCIATING).
- * When we set the state to IEEE80211_NOLINK it is possible
- * that the RX path run an attempt to associate, but
- * both ieee80211_softmac_check_all_nets and the
- * RX path works with ieee->lock held so there are no
- * problems. If we are still disassociated then start a scan.
- * the lock here is necessary to ensure no one try to start
- * an association procedure when we have just checked the
- * state and we are going to start the scan.
- */
- ieee->state = IEEE80211_NOLINK;
- ieee->beinretry = true;
- ieee80211_softmac_check_all_nets(ieee);
-
- spin_lock_irqsave(&ieee->lock, flags);
-
- if (ieee->state == IEEE80211_NOLINK) {
- ieee->beinretry = false;
- ieee->actscanning = true;
- ieee80211_rtl_start_scan(ieee);
- }
- if (ieee->state == IEEE80211_NOLINK)
- notify_wx_assoc_event(ieee);
- spin_unlock_irqrestore(&ieee->lock, flags);
-
-exit:
- up(&ieee->wx_sem);
-}
-
-struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee)
-{
- u8 broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-
- struct sk_buff *skb = NULL;
- struct ieee80211_probe_response *b;
-
- skb = ieee80211_probe_resp(ieee, broadcast_addr);
- if (!skb)
- return NULL;
-
- b = (struct ieee80211_probe_response *) skb->data;
- b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON);
-
- return skb;
-}
-
-struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee)
-{
- struct sk_buff *skb;
- struct ieee80211_probe_response *b;
-
- skb = ieee80211_get_beacon_(ieee);
- if (!skb)
- return NULL;
-
- b = (struct ieee80211_probe_response *) skb->data;
- b->header.seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
-
- if (ieee->seq_ctrl[0] == 0xFFF)
- ieee->seq_ctrl[0] = 0;
- else
- ieee->seq_ctrl[0]++;
-
- return skb;
-}
-
-void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee)
-{
- ieee->sync_scan_hurryup = 1;
- down(&ieee->wx_sem);
- ieee80211_stop_protocol(ieee);
- up(&ieee->wx_sem);
-}
-
-void ieee80211_stop_protocol(struct ieee80211_device *ieee)
-{
- if (!ieee->proto_started)
- return;
-
- ieee->proto_started = 0;
-
- ieee80211_stop_send_beacons(ieee);
- if ((ieee->iw_mode == IW_MODE_INFRA) && (ieee->state == IEEE80211_LINKED))
- SendDisassociation(ieee, NULL, WLAN_REASON_DISASSOC_STA_HAS_LEFT);
-
- del_timer_sync(&ieee->associate_timer);
- cancel_delayed_work(&ieee->associate_retry_wq);
- cancel_delayed_work(&ieee->start_ibss_wq);
- ieee80211_stop_scan(ieee);
-
- ieee80211_disassociate(ieee);
-}
-
-void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee)
-{
- ieee->sync_scan_hurryup = 0;
- down(&ieee->wx_sem);
- ieee80211_start_protocol(ieee);
- up(&ieee->wx_sem);
-}
-
-void ieee80211_start_protocol(struct ieee80211_device *ieee)
-{
- short ch = 0;
- int i = 0;
-
- if (ieee->proto_started)
- return;
-
- ieee->proto_started = 1;
-
- if (ieee->current_network.channel == 0) {
- do {
- ch++;
- if (ch > MAX_CHANNEL_NUMBER)
- return; /* no channel found */
-
- } while (!GET_DOT11D_INFO(ieee)->channel_map[ch]);
-
- ieee->current_network.channel = ch;
- }
-
- if (ieee->current_network.beacon_interval == 0)
- ieee->current_network.beacon_interval = 100;
- ieee->set_chan(ieee->dev, ieee->current_network.channel);
-
- for (i = 0; i < 17; i++) {
- ieee->last_rxseq_num[i] = -1;
- ieee->last_rxfrag_num[i] = -1;
- ieee->last_packet_time[i] = 0;
- }
-
- ieee->init_wmmparam_flag = 0; /* reinitialize AC_xx_PARAM registers. */
-
- /* if the user set the MAC of the ad-hoc cell and then
- * switch to managed mode, shall we make sure that association
- * attempts does not fail just because the user provide the essid
- * and the nic is still checking for the AP MAC ??
- */
- switch (ieee->iw_mode) {
- case IW_MODE_AUTO:
- ieee->iw_mode = IW_MODE_INFRA;
- /* not set break here intentionly */
- case IW_MODE_INFRA:
- ieee80211_start_bss(ieee);
- break;
-
- case IW_MODE_ADHOC:
- ieee80211_start_ibss(ieee);
- break;
-
- case IW_MODE_MASTER:
- ieee80211_start_master_bss(ieee);
- break;
-
- case IW_MODE_MONITOR:
- ieee80211_start_monitor_mode(ieee);
- break;
-
- default:
- ieee->iw_mode = IW_MODE_INFRA;
- ieee80211_start_bss(ieee);
- break;
- }
-}
-
-#define DRV_NAME "Ieee80211"
-void ieee80211_softmac_init(struct ieee80211_device *ieee)
-{
- int i;
- memset(&ieee->current_network, 0, sizeof(struct ieee80211_network));
-
- ieee->state = IEEE80211_NOLINK;
- ieee->sync_scan_hurryup = 0;
- for (i = 0; i < 5; i++)
- ieee->seq_ctrl[i] = 0;
-
- ieee->assoc_id = 0;
- ieee->queue_stop = 0;
- ieee->scanning = 0;
- ieee->softmac_features = 0; /* so IEEE2100-like driver are happy */
- ieee->wap_set = 0;
- ieee->ssid_set = 0;
- ieee->proto_started = 0;
- ieee->basic_rate = IEEE80211_DEFAULT_BASIC_RATE;
- ieee->rate = 3;
- ieee->ps = IEEE80211_PS_MBCAST|IEEE80211_PS_UNICAST;
- ieee->sta_sleep = 0;
- ieee->bInactivePs = false;
- ieee->actscanning = false;
- ieee->ListenInterval = 2;
- ieee->NumRxDataInPeriod = 0;
- ieee->NumRxBcnInPeriod = 0;
- ieee->NumRxOkTotal = 0;
- ieee->NumRxUnicast = 0; /* for keep alive */
- ieee->beinretry = false;
- ieee->bHwRadioOff = false;
-
- init_mgmt_queue(ieee);
-
- ieee->tx_pending.txb = NULL;
-
- init_timer(&ieee->associate_timer);
- ieee->associate_timer.data = (unsigned long)ieee;
- ieee->associate_timer.function = ieee80211_associate_abort_cb;
-
- init_timer(&ieee->beacon_timer);
- ieee->beacon_timer.data = (unsigned long) ieee;
- ieee->beacon_timer.function = ieee80211_send_beacon_cb;
-
- ieee->wq = create_workqueue(DRV_NAME);
-
- INIT_DELAYED_WORK(&ieee->start_ibss_wq, (void *) ieee80211_start_ibss_wq);
- INIT_WORK(&ieee->associate_complete_wq, (void *) ieee80211_associate_complete_wq);
- INIT_WORK(&ieee->associate_procedure_wq, (void *) ieee80211_associate_procedure_wq);
- INIT_DELAYED_WORK(&ieee->softmac_scan_wq, (void *) ieee80211_softmac_scan_wq);
- INIT_DELAYED_WORK(&ieee->associate_retry_wq, (void *) ieee80211_associate_retry_wq);
- INIT_WORK(&ieee->wx_sync_scan_wq, (void *) ieee80211_wx_sync_scan_wq);
-
- sema_init(&ieee->wx_sem, 1);
- sema_init(&ieee->scan_sem, 1);
-
- spin_lock_init(&ieee->mgmt_tx_lock);
- spin_lock_init(&ieee->beacon_lock);
-
- tasklet_init(&ieee->ps_task,
- (void(*)(unsigned long)) ieee80211_sta_ps,
- (unsigned long)ieee);
- ieee->pDot11dInfo = kmalloc(sizeof(RT_DOT11D_INFO), GFP_ATOMIC);
-}
-
-void ieee80211_softmac_free(struct ieee80211_device *ieee)
-{
- down(&ieee->wx_sem);
-
- del_timer_sync(&ieee->associate_timer);
- cancel_delayed_work(&ieee->associate_retry_wq);
-
- /* add for RF power on power of */
- cancel_delayed_work(&ieee->GPIOChangeRFWorkItem);
-
- destroy_workqueue(ieee->wq);
- kfree(ieee->pDot11dInfo);
- up(&ieee->wx_sem);
-}
-
-/* Start of WPA code. This is stolen from the ipw2200 driver */
-static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value)
-{
- /* This is called when wpa_supplicant loads and closes the driver
- * interface. */
- printk("%s WPA\n", value ? "enabling" : "disabling");
- ieee->wpa_enabled = value;
- return 0;
-}
-
-static void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee, char *wpa_ie,
- int wpa_ie_len)
-{
- /* make sure WPA is enabled */
- ieee80211_wpa_enable(ieee, 1);
-
- ieee80211_disassociate(ieee);
-}
-
-static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command,
- int reason)
-{
- int ret = 0;
-
- switch (command) {
- case IEEE_MLME_STA_DEAUTH:
- /* silently ignore */
- break;
-
- case IEEE_MLME_STA_DISASSOC:
- ieee80211_disassociate(ieee);
- break;
-
- default:
- printk("Unknown MLME request: %d\n", command);
- ret = -EOPNOTSUPP;
- }
-
- return ret;
-}
-
-static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee,
- struct ieee_param *param, int plen)
-{
- u8 *buf;
-
- if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
- (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL))
- return -EINVAL;
-
- if (param->u.wpa_ie.len) {
- buf = kmemdup(param->u.wpa_ie.data, param->u.wpa_ie.len,
- GFP_KERNEL);
- if (buf == NULL)
- return -ENOMEM;
-
- kfree(ieee->wpa_ie);
- ieee->wpa_ie = buf;
- ieee->wpa_ie_len = param->u.wpa_ie.len;
- } else {
- kfree(ieee->wpa_ie);
- ieee->wpa_ie = NULL;
- ieee->wpa_ie_len = 0;
- }
-
- ieee80211_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len);
- return 0;
-}
-
-#define AUTH_ALG_OPEN_SYSTEM 0x1
-#define AUTH_ALG_SHARED_KEY 0x2
-
-static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value)
-{
- struct ieee80211_security sec = {
- .flags = SEC_AUTH_MODE,
- };
- int ret = 0;
-
- if (value & AUTH_ALG_SHARED_KEY) {
- sec.auth_mode = WLAN_AUTH_SHARED_KEY;
- ieee->open_wep = 0;
- } else {
- sec.auth_mode = WLAN_AUTH_OPEN;
- ieee->open_wep = 1;
- }
-
- if (ieee->set_security)
- ieee->set_security(ieee->dev, &sec);
- else
- ret = -EOPNOTSUPP;
-
- return ret;
-}
-
-static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name,
- u32 value)
-{
- int ret = 0;
- unsigned long flags;
-
- switch (name) {
- case IEEE_PARAM_WPA_ENABLED:
- ret = ieee80211_wpa_enable(ieee, value);
- break;
-
- case IEEE_PARAM_TKIP_COUNTERMEASURES:
- ieee->tkip_countermeasures = value;
- break;
-
- case IEEE_PARAM_DROP_UNENCRYPTED: {
- /* HACK:
- *
- * wpa_supplicant calls set_wpa_enabled when the driver
- * is loaded and unloaded, regardless of if WPA is being
- * used. No other calls are made which can be used to
- * determine if encryption will be used or not prior to
- * association being expected. If encryption is not being
- * used, drop_unencrypted is set to false, else true -- we
- * can use this to determine if the CAP_PRIVACY_ON bit should
- * be set.
- */
- struct ieee80211_security sec = {
- .flags = SEC_ENABLED,
- .enabled = value,
- };
- ieee->drop_unencrypted = value;
- /* We only change SEC_LEVEL for open mode. Others
- * are set by ipw_wpa_set_encryption.
- */
- if (!value) {
- sec.flags |= SEC_LEVEL;
- sec.level = SEC_LEVEL_0;
- } else {
- sec.flags |= SEC_LEVEL;
- sec.level = SEC_LEVEL_1;
- }
- if (ieee->set_security)
- ieee->set_security(ieee->dev, &sec);
- break;
- }
-
- case IEEE_PARAM_PRIVACY_INVOKED:
- ieee->privacy_invoked = value;
- break;
- case IEEE_PARAM_AUTH_ALGS:
- ret = ieee80211_wpa_set_auth_algs(ieee, value);
- break;
- case IEEE_PARAM_IEEE_802_1X:
- ieee->ieee802_1x = value;
- break;
- case IEEE_PARAM_WPAX_SELECT:
- spin_lock_irqsave(&ieee->wpax_suitlist_lock, flags);
- ieee->wpax_type_set = 1;
- ieee->wpax_type_notify = value;
- spin_unlock_irqrestore(&ieee->wpax_suitlist_lock, flags);
- break;
- default:
- printk("Unknown WPA param: %d\n", name);
- ret = -EOPNOTSUPP;
- }
-
- return ret;
-}
-
-/* implementation borrowed from hostap driver */
-
-static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
- struct ieee_param *param, int param_len)
-{
- int ret = 0;
-
- struct ieee80211_crypto_ops *ops;
- struct ieee80211_crypt_data **crypt;
-
- struct ieee80211_security sec = {
- .flags = 0,
- };
-
- param->u.crypt.err = 0;
- param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
-
- if (param_len !=
- (int) ((char *) param->u.crypt.key - (char *) param) +
- param->u.crypt.key_len) {
- printk("Len mismatch %d, %d\n", param_len,
- param->u.crypt.key_len);
- return -EINVAL;
- }
- if (is_broadcast_ether_addr(param->sta_addr)) {
- if (param->u.crypt.idx >= WEP_KEYS)
- return -EINVAL;
- crypt = &ieee->crypt[param->u.crypt.idx];
- } else {
- return -EINVAL;
- }
-
- if (strcmp(param->u.crypt.alg, "none") == 0) {
- if (crypt) {
- sec.enabled = 0;
- /* FIXME FIXME */
- sec.level = SEC_LEVEL_0;
- sec.flags |= SEC_ENABLED | SEC_LEVEL;
- ieee80211_crypt_delayed_deinit(ieee, crypt);
- }
- goto done;
- }
- sec.enabled = 1;
- /* FIXME FIXME */
- sec.flags |= SEC_ENABLED;
-
- /* IPW HW cannot build TKIP MIC, host decryption still needed. */
- if (!(ieee->host_encrypt || ieee->host_decrypt) &&
- strcmp(param->u.crypt.alg, "TKIP"))
- goto skip_host_crypt;
-
- ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
- if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0)
- ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
- else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0)
- ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
- else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0)
- ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
- if (ops == NULL) {
- printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
- param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
- ret = -EINVAL;
- goto done;
- }
-
- if (*crypt == NULL || (*crypt)->ops != ops) {
- struct ieee80211_crypt_data *new_crypt;
-
- ieee80211_crypt_delayed_deinit(ieee, crypt);
-
- new_crypt = kmalloc(sizeof(*new_crypt), GFP_KERNEL);
- if (new_crypt == NULL) {
- ret = -ENOMEM;
- goto done;
- }
- memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
- new_crypt->ops = ops;
- if (new_crypt->ops)
- new_crypt->priv =
- new_crypt->ops->init(param->u.crypt.idx);
-
- if (new_crypt->priv == NULL) {
- kfree(new_crypt);
- param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED;
- ret = -EINVAL;
- goto done;
- }
-
- *crypt = new_crypt;
- }
-
- if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
- (*crypt)->ops->set_key(param->u.crypt.key,
- param->u.crypt.key_len, param->u.crypt.seq,
- (*crypt)->priv) < 0) {
- printk("key setting failed\n");
- param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED;
- ret = -EINVAL;
- goto done;
- }
-
- skip_host_crypt:
- if (param->u.crypt.set_tx) {
- ieee->tx_keyidx = param->u.crypt.idx;
- sec.active_key = param->u.crypt.idx;
- sec.flags |= SEC_ACTIVE_KEY;
- } else
- sec.flags &= ~SEC_ACTIVE_KEY;
-
- if (param->u.crypt.alg != NULL) {
- memcpy(sec.keys[param->u.crypt.idx],
- param->u.crypt.key,
- param->u.crypt.key_len);
- sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
- sec.flags |= (1 << param->u.crypt.idx);
-
- if (strcmp(param->u.crypt.alg, "WEP") == 0) {
- sec.flags |= SEC_LEVEL;
- sec.level = SEC_LEVEL_1;
- } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
- sec.flags |= SEC_LEVEL;
- sec.level = SEC_LEVEL_2;
- } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
- sec.flags |= SEC_LEVEL;
- sec.level = SEC_LEVEL_3;
- }
- }
- done:
- if (ieee->set_security)
- ieee->set_security(ieee->dev, &sec);
-
- /* Do not reset port if card is in Managed mode since resetting will
- * generate new IEEE 802.11 authentication which may end up in looping
- * with IEEE 802.1X. If your hardware requires a reset after WEP
- * configuration (for example... Prism2), implement the reset_port in
- * the callbacks structures used to initialize the 802.11 stack. */
- if (ieee->reset_on_keychange &&
- ieee->iw_mode != IW_MODE_INFRA &&
- ieee->reset_port &&
- ieee->reset_port(ieee->dev)) {
- printk("reset_port failed\n");
- param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED;
- return -EINVAL;
- }
-
- return ret;
-}
-
-int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee,
- struct iw_point *p)
-{
- struct ieee_param *param;
- int ret = 0;
-
- down(&ieee->wx_sem);
-
- if (p->length < sizeof(struct ieee_param) || !p->pointer) {
- ret = -EINVAL;
- goto out;
- }
-
- param = memdup_user(p->pointer, p->length);
- if (IS_ERR(param)) {
- ret = PTR_ERR(param);
- goto out;
- }
-
- switch (param->cmd) {
- case IEEE_CMD_SET_WPA_PARAM:
- ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name,
- param->u.wpa_param.value);
- break;
- case IEEE_CMD_SET_WPA_IE:
- ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length);
- break;
- case IEEE_CMD_SET_ENCRYPTION:
- ret = ieee80211_wpa_set_encryption(ieee, param, p->length);
- break;
- case IEEE_CMD_MLME:
- ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command,
- param->u.mlme.reason_code);
- break;
- default:
- printk("Unknown WPA supplicant request: %d\n", param->cmd);
- ret = -EOPNOTSUPP;
- break;
- }
-
- if (ret == 0 && copy_to_user(p->pointer, param, p->length))
- ret = -EFAULT;
-
- kfree(param);
-out:
- up(&ieee->wx_sem);
-
- return ret;
-}
-
-void notify_wx_assoc_event(struct ieee80211_device *ieee)
-{
- union iwreq_data wrqu;
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
- if (ieee->state == IEEE80211_LINKED)
- memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN);
- else
- memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
- wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL);
-}
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c
deleted file mode 100644
index 46f35644126c..000000000000
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c
+++ /dev/null
@@ -1,567 +0,0 @@
-/* IEEE 802.11 SoftMAC layer
- * Copyright (c) 2005 Andrea Merello <andrea.merello@gmail.com>
- *
- * Mostly extracted from the rtl8180-sa2400 driver for the
- * in-kernel generic ieee802.11 stack.
- *
- * Some pieces of code might be stolen from ipw2100 driver
- * copyright of who own it's copyright ;-)
- *
- * PS wx handler mostly stolen from hostap, copyright who
- * own it's copyright ;-)
- *
- * released under the GPL
- */
-
-
-#include <linux/etherdevice.h>
-
-#include "ieee80211.h"
-
-/* FIXME: add A freqs */
-
-const long ieee80211_wlan_frequencies[] = {
- 2412, 2417, 2422, 2427,
- 2432, 2437, 2442, 2447,
- 2452, 2457, 2462, 2467,
- 2472, 2484
-};
-
-
-int ieee80211_wx_set_freq(struct ieee80211_device *ieee,
- struct iw_request_info *a, union iwreq_data *wrqu,
- char *b)
-{
- int ret;
- struct iw_freq *fwrq = &wrqu->freq;
-// printk("in %s\n",__func__);
- down(&ieee->wx_sem);
-
- if (ieee->iw_mode == IW_MODE_INFRA) {
- ret = -EOPNOTSUPP;
- goto out;
- }
-
- /* if setting by freq convert to channel */
- if (fwrq->e == 1) {
- if ((fwrq->m >= (int) 2.412e8 &&
- fwrq->m <= (int) 2.487e8)) {
- int f = fwrq->m / 100000;
- int c = 0;
-
- while ((c < 14) && (f != ieee80211_wlan_frequencies[c]))
- c++;
-
- /* hack to fall through */
- fwrq->e = 0;
- fwrq->m = c + 1;
- }
- }
-
- if (fwrq->e > 0 || fwrq->m > 14 || fwrq->m < 1) {
- ret = -EOPNOTSUPP;
- goto out;
-
- } else { /* Set the channel */
-
-
- ieee->current_network.channel = fwrq->m;
- ieee->set_chan(ieee->dev, ieee->current_network.channel);
-
- if (ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER)
- if (ieee->state == IEEE80211_LINKED) {
- ieee80211_stop_send_beacons(ieee);
- ieee80211_start_send_beacons(ieee);
- }
- }
-
- ret = 0;
-out:
- up(&ieee->wx_sem);
- return ret;
-}
-
-
-int ieee80211_wx_get_freq(struct ieee80211_device *ieee,
- struct iw_request_info *a, union iwreq_data *wrqu,
- char *b)
-{
- struct iw_freq *fwrq = &wrqu->freq;
-
- if (ieee->current_network.channel == 0)
- return -1;
-
- fwrq->m = ieee->current_network.channel;
- fwrq->e = 0;
-
- return 0;
-}
-
-int ieee80211_wx_get_wap(struct ieee80211_device *ieee,
- struct iw_request_info *info, union iwreq_data *wrqu,
- char *extra)
-{
- unsigned long flags;
-
- wrqu->ap_addr.sa_family = ARPHRD_ETHER;
-
- if (ieee->iw_mode == IW_MODE_MONITOR)
- return -1;
-
- /* We want avoid to give to the user inconsistent infos*/
- spin_lock_irqsave(&ieee->lock, flags);
-
- if (ieee->state != IEEE80211_LINKED &&
- ieee->state != IEEE80211_LINKED_SCANNING &&
- ieee->wap_set == 0)
-
- memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
- else
- memcpy(wrqu->ap_addr.sa_data,
- ieee->current_network.bssid, ETH_ALEN);
-
- spin_unlock_irqrestore(&ieee->lock, flags);
-
- return 0;
-}
-
-
-int ieee80211_wx_set_wap(struct ieee80211_device *ieee,
- struct iw_request_info *info, union iwreq_data *awrq,
- char *extra)
-{
-
- int ret = 0;
- unsigned long flags;
-
- short ifup = ieee->proto_started;//dev->flags & IFF_UP;
- struct sockaddr *temp = (struct sockaddr *)awrq;
-
- //printk("=======Set WAP:");
- ieee->sync_scan_hurryup = 1;
-
- down(&ieee->wx_sem);
- /* use ifconfig hw ether */
- if (ieee->iw_mode == IW_MODE_MASTER) {
- ret = -1;
- goto out;
- }
-
- if (temp->sa_family != ARPHRD_ETHER) {
- ret = -EINVAL;
- goto out;
- }
-
- if (ifup)
- ieee80211_stop_protocol(ieee);
-
- /* just to avoid to give inconsistent infos in the
- * get wx method. not really needed otherwise
- */
- spin_lock_irqsave(&ieee->lock, flags);
-
- memcpy(ieee->current_network.bssid, temp->sa_data, ETH_ALEN);
- ieee->wap_set = !is_zero_ether_addr(temp->sa_data);
- //printk(" %x:%x:%x:%x:%x:%x\n", ieee->current_network.bssid[0],ieee->current_network.bssid[1],ieee->current_network.bssid[2],ieee->current_network.bssid[3],ieee->current_network.bssid[4],ieee->current_network.bssid[5]);
-
- spin_unlock_irqrestore(&ieee->lock, flags);
-
- if (ifup)
- ieee80211_start_protocol(ieee);
-
-out:
- up(&ieee->wx_sem);
- return ret;
-}
-
-int ieee80211_wx_get_essid(struct ieee80211_device *ieee,
- struct iw_request_info *a, union iwreq_data *wrqu,
- char *b)
-{
- int len, ret = 0;
- unsigned long flags;
-
- if (ieee->iw_mode == IW_MODE_MONITOR)
- return -1;
-
- /* We want avoid to give to the user inconsistent infos*/
- spin_lock_irqsave(&ieee->lock, flags);
-
- if (ieee->current_network.ssid[0] == '\0' ||
- ieee->current_network.ssid_len == 0){
- ret = -1;
- goto out;
- }
-
- if (ieee->state != IEEE80211_LINKED &&
- ieee->state != IEEE80211_LINKED_SCANNING &&
- ieee->ssid_set == 0){
- ret = -1;
- goto out;
- }
- len = ieee->current_network.ssid_len;
- wrqu->essid.length = len;
- strncpy(b, ieee->current_network.ssid, len);
- wrqu->essid.flags = 1;
-
-out:
- spin_unlock_irqrestore(&ieee->lock, flags);
-
- return ret;
-
-}
-
-int ieee80211_wx_set_rate(struct ieee80211_device *ieee,
- struct iw_request_info *info, union iwreq_data *wrqu,
- char *extra)
-{
-
- u32 target_rate = wrqu->bitrate.value;
-
- //added by lizhaoming for auto mode
- if (target_rate == -1)
- ieee->rate = 110;
- else
- ieee->rate = target_rate/100000;
-
- //FIXME: we might want to limit rate also in management protocols.
- return 0;
-}
-
-
-
-int ieee80211_wx_get_rate(struct ieee80211_device *ieee,
- struct iw_request_info *info, union iwreq_data *wrqu,
- char *extra)
-{
-
- wrqu->bitrate.value = ieee->rate * 100000;
-
- return 0;
-}
-
-int ieee80211_wx_set_mode(struct ieee80211_device *ieee,
- struct iw_request_info *a, union iwreq_data *wrqu,
- char *b)
-{
-
- ieee->sync_scan_hurryup = 1;
-
- down(&ieee->wx_sem);
-
- if (wrqu->mode == ieee->iw_mode)
- goto out;
-
- if (wrqu->mode == IW_MODE_MONITOR)
- ieee->dev->type = ARPHRD_IEEE80211;
- else
- ieee->dev->type = ARPHRD_ETHER;
-
- if (!ieee->proto_started) {
- ieee->iw_mode = wrqu->mode;
- } else {
- ieee80211_stop_protocol(ieee);
- ieee->iw_mode = wrqu->mode;
- ieee80211_start_protocol(ieee);
- }
-
-out:
- up(&ieee->wx_sem);
- return 0;
-}
-
-
-void ieee80211_wx_sync_scan_wq(struct work_struct *work)
-{
- struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, wx_sync_scan_wq);
- short chan;
-
- chan = ieee->current_network.channel;
-
- if (ieee->data_hard_stop)
- ieee->data_hard_stop(ieee->dev);
-
- ieee80211_stop_send_beacons(ieee);
-
- ieee->state = IEEE80211_LINKED_SCANNING;
- ieee->link_change(ieee->dev);
-
- ieee80211_start_scan_syncro(ieee);
-
- ieee->set_chan(ieee->dev, chan);
-
- ieee->state = IEEE80211_LINKED;
- ieee->link_change(ieee->dev);
-
- if (ieee->data_hard_resume)
- ieee->data_hard_resume(ieee->dev);
-
- if (ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER)
- ieee80211_start_send_beacons(ieee);
-
- //YJ,add,080828, In prevent of lossing ping packet during scanning
- //ieee80211_sta_ps_send_null_frame(ieee, false);
- //YJ,add,080828,end
-
- up(&ieee->wx_sem);
-
-}
-
-int ieee80211_wx_set_scan(struct ieee80211_device *ieee,
- struct iw_request_info *a, union iwreq_data *wrqu,
- char *b)
-{
- int ret = 0;
-
- down(&ieee->wx_sem);
-
- if (ieee->iw_mode == IW_MODE_MONITOR || !(ieee->proto_started)) {
- ret = -1;
- goto out;
- }
- //YJ,add,080828
- //In prevent of lossing ping packet during scanning
- //ieee80211_sta_ps_send_null_frame(ieee, true);
- //YJ,add,080828,end
-
- if (ieee->state == IEEE80211_LINKED) {
- queue_work(ieee->wq, &ieee->wx_sync_scan_wq);
- /* intentionally forget to up sem */
- return 0;
- }
-
-out:
- up(&ieee->wx_sem);
- return ret;
-}
-
-int ieee80211_wx_set_essid(struct ieee80211_device *ieee,
- struct iw_request_info *a, union iwreq_data *wrqu,
- char *extra)
-{
-
- int ret = 0, len;
- short proto_started;
- unsigned long flags;
-
- ieee->sync_scan_hurryup = 1;
-
- down(&ieee->wx_sem);
-
- proto_started = ieee->proto_started;
-
- if (wrqu->essid.length > IW_ESSID_MAX_SIZE) {
- ret = -E2BIG;
- goto out;
- }
-
- if (ieee->iw_mode == IW_MODE_MONITOR) {
- ret = -1;
- goto out;
- }
-
- if (proto_started)
- ieee80211_stop_protocol(ieee);
-
- /* this is just to be sure that the GET wx callback
- * has consistent infos. not needed otherwise
- */
- spin_lock_irqsave(&ieee->lock, flags);
-
- if (wrqu->essid.flags && wrqu->essid.length) {
-//YJ,modified,080819
- len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ? (wrqu->essid.length) : IW_ESSID_MAX_SIZE;
- memset(ieee->current_network.ssid, 0, ieee->current_network.ssid_len); //YJ,add,080819
- strncpy(ieee->current_network.ssid, extra, len);
- ieee->current_network.ssid_len = len;
- ieee->ssid_set = 1;
-//YJ,modified,080819,end
-
- //YJ,add,080819,for hidden ap
- if (len == 0) {
- memset(ieee->current_network.bssid, 0, ETH_ALEN);
- ieee->current_network.capability = 0;
- }
- //YJ,add,080819,for hidden ap,end
- } else {
- ieee->ssid_set = 0;
- ieee->current_network.ssid[0] = '\0';
- ieee->current_network.ssid_len = 0;
- }
- //printk("==========set essid %s!\n",ieee->current_network.ssid);
- spin_unlock_irqrestore(&ieee->lock, flags);
-
- if (proto_started)
- ieee80211_start_protocol(ieee);
-out:
- up(&ieee->wx_sem);
- return ret;
-}
-
-int ieee80211_wx_get_mode(struct ieee80211_device *ieee,
- struct iw_request_info *a, union iwreq_data *wrqu,
- char *b)
-{
-
- wrqu->mode = ieee->iw_mode;
- return 0;
-}
-
-int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee,
- struct iw_request_info *info, union iwreq_data *wrqu,
- char *extra)
-{
-
- int *parms = (int *)extra;
- int enable = (parms[0] > 0);
- short prev = ieee->raw_tx;
-
- down(&ieee->wx_sem);
-
- if (enable)
- ieee->raw_tx = 1;
- else
- ieee->raw_tx = 0;
-
- netdev_info(ieee->dev, "raw TX is %s\n",
- ieee->raw_tx ? "enabled" : "disabled");
-
- if (ieee->iw_mode == IW_MODE_MONITOR) {
- if (prev == 0 && ieee->raw_tx) {
- if (ieee->data_hard_resume)
- ieee->data_hard_resume(ieee->dev);
-
- netif_carrier_on(ieee->dev);
- }
-
- if (prev && ieee->raw_tx == 1)
- netif_carrier_off(ieee->dev);
- }
-
- up(&ieee->wx_sem);
-
- return 0;
-}
-
-int ieee80211_wx_get_name(struct ieee80211_device *ieee,
- struct iw_request_info *info, union iwreq_data *wrqu,
- char *extra)
-{
- strlcpy(wrqu->name, "802.11", IFNAMSIZ);
- if (ieee->modulation & IEEE80211_CCK_MODULATION) {
- strlcat(wrqu->name, "b", IFNAMSIZ);
- if (ieee->modulation & IEEE80211_OFDM_MODULATION)
- strlcat(wrqu->name, "/g", IFNAMSIZ);
- } else if (ieee->modulation & IEEE80211_OFDM_MODULATION)
- strlcat(wrqu->name, "g", IFNAMSIZ);
-
- if ((ieee->state == IEEE80211_LINKED) ||
- (ieee->state == IEEE80211_LINKED_SCANNING))
- strlcat(wrqu->name, " link", IFNAMSIZ);
- else if (ieee->state != IEEE80211_NOLINK)
- strlcat(wrqu->name, " .....", IFNAMSIZ);
-
-
- return 0;
-}
-
-
-/* this is mostly stolen from hostap */
-int ieee80211_wx_set_power(struct ieee80211_device *ieee,
- struct iw_request_info *info, union iwreq_data *wrqu,
- char *extra)
-{
- int ret = 0;
-
- if ((!ieee->sta_wake_up) ||
- (!ieee->ps_request_tx_ack) ||
- (!ieee->enter_sleep_state) ||
- (!ieee->ps_is_queue_empty)) {
-
- printk("ERROR. PS mode tried to be use but driver missed a callback\n\n");
-
- return -1;
- }
-
- down(&ieee->wx_sem);
-
- if (wrqu->power.disabled) {
- ieee->ps = IEEE80211_PS_DISABLED;
-
- goto exit;
- }
- switch (wrqu->power.flags & IW_POWER_MODE) {
- case IW_POWER_UNICAST_R:
- ieee->ps = IEEE80211_PS_UNICAST;
-
- break;
- case IW_POWER_ALL_R:
- ieee->ps = IEEE80211_PS_UNICAST | IEEE80211_PS_MBCAST;
- break;
-
- case IW_POWER_ON:
- ieee->ps = IEEE80211_PS_DISABLED;
- break;
-
- default:
- ret = -EINVAL;
- goto exit;
- }
-
- if (wrqu->power.flags & IW_POWER_TIMEOUT) {
-
- ieee->ps_timeout = wrqu->power.value / 1000;
- printk("Timeout %d\n", ieee->ps_timeout);
- }
-
- if (wrqu->power.flags & IW_POWER_PERIOD) {
-
- ret = -EOPNOTSUPP;
- goto exit;
- //wrq->value / 1024;
-
- }
-exit:
- up(&ieee->wx_sem);
- return ret;
-
-}
-
-/* this is stolen from hostap */
-int ieee80211_wx_get_power(struct ieee80211_device *ieee,
- struct iw_request_info *info, union iwreq_data *wrqu,
- char *extra)
-{
- int ret = 0;
-
- down(&ieee->wx_sem);
-
- if (ieee->ps == IEEE80211_PS_DISABLED) {
- wrqu->power.disabled = 1;
- goto exit;
- }
-
- wrqu->power.disabled = 0;
-
-// if ((wrqu->power.flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
- wrqu->power.flags = IW_POWER_TIMEOUT;
- wrqu->power.value = ieee->ps_timeout * 1000;
-// } else {
-// ret = -EOPNOTSUPP;
-// goto exit;
- //wrqu->power.flags = IW_POWER_PERIOD;
- //wrqu->power.value = ieee->current_network.dtim_period *
- // ieee->current_network.beacon_interval * 1024;
-// }
-
-
- if (ieee->ps & IEEE80211_PS_MBCAST)
- wrqu->power.flags |= IW_POWER_ALL_R;
- else
- wrqu->power.flags |= IW_POWER_UNICAST_R;
-
-exit:
- up(&ieee->wx_sem);
- return ret;
-
-}
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c
deleted file mode 100644
index 0dc5ae414270..000000000000
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c
+++ /dev/null
@@ -1,591 +0,0 @@
-/******************************************************************************
-
- Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved.
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of version 2 of the GNU General Public License 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., 59
- Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
- The full GNU General Public License is included in this distribution in the
- file called LICENSE.
-
- Contact Information:
- James P. Ketrenos <ipw2100-admin@linux.intel.com>
- Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-
-******************************************************************************
-
- Few modifications for Realtek's Wi-Fi drivers by
- Andrea Merello <andrea.merello@gmail.com>
-
- A special thanks goes to Realtek for their support !
-
-******************************************************************************/
-
-#include <linux/compiler.h>
-#include <linux/errno.h>
-#include <linux/if_arp.h>
-#include <linux/in6.h>
-#include <linux/in.h>
-#include <linux/ip.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/pci.h>
-#include <linux/proc_fs.h>
-#include <linux/skbuff.h>
-#include <linux/slab.h>
-#include <linux/tcp.h>
-#include <linux/types.h>
-#include <linux/wireless.h>
-#include <linux/etherdevice.h>
-#include <asm/uaccess.h>
-#include <linux/if_vlan.h>
-
-#include "ieee80211.h"
-
-
-/*
-
-
-802.11 Data Frame
-
-
-802.11 frame_contorl for data frames - 2 bytes
- ,-----------------------------------------------------------------------------------------.
-bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e |
- |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
-val | 0 | 0 | 0 | 1 | x | 0 | 0 | 0 | 1 | 0 | x | x | x | x | x |
- |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
-desc | ^-ver-^ | ^type-^ | ^-----subtype-----^ | to |from |more |retry| pwr |more |wep |
- | | | x=0 data,x=1 data+ack | DS | DS |frag | | mgm |data | |
- '-----------------------------------------------------------------------------------------'
- /\
- |
-802.11 Data Frame |
- ,--------- 'ctrl' expands to >-----------'
- |
- ,--'---,-------------------------------------------------------------.
-Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 |
- |------|------|---------|---------|---------|------|---------|------|
-Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | Frame | fcs |
- | | tion | (BSSID) | | | ence | data | |
- `--------------------------------------------------| |------'
-Total: 28 non-data bytes `----.----'
- |
- .- 'Frame data' expands to <---------------------------'
- |
- V
- ,---------------------------------------------------.
-Bytes | 1 | 1 | 1 | 3 | 2 | 0-2304 |
- |------|------|---------|----------|------|---------|
-Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP |
- | DSAP | SSAP | | | | Packet |
- | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | |
- `-----------------------------------------| |
-Total: 8 non-data bytes `----.----'
- |
- .- 'IP Packet' expands, if WEP enabled, to <--'
- |
- V
- ,-----------------------.
-Bytes | 4 | 0-2296 | 4 |
- |-----|-----------|-----|
-Desc. | IV | Encrypted | ICV |
- | | IP Packet | |
- `-----------------------'
-Total: 8 non-data bytes
-
-
-802.3 Ethernet Data Frame
-
- ,-----------------------------------------.
-Bytes | 6 | 6 | 2 | Variable | 4 |
- |-------|-------|------|-----------|------|
-Desc. | Dest. | Source| Type | IP Packet | fcs |
- | MAC | MAC | | | |
- `-----------------------------------------'
-Total: 18 non-data bytes
-
-In the event that fragmentation is required, the incoming payload is split into
-N parts of size ieee->fts. The first fragment contains the SNAP header and the
-remaining packets are just data.
-
-If encryption is enabled, each fragment payload size is reduced by enough space
-to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP)
-So if you have 1500 bytes of payload with ieee->fts set to 500 without
-encryption it will take 3 frames. With WEP it will take 4 frames as the
-payload of each frame is reduced to 492 bytes.
-
-* SKB visualization
-*
-* ,- skb->data
-* |
-* | ETHERNET HEADER ,-<-- PAYLOAD
-* | | 14 bytes from skb->data
-* | 2 bytes for Type --> ,T. | (sizeof ethhdr)
-* | | | |
-* |,-Dest.--. ,--Src.---. | | |
-* | 6 bytes| | 6 bytes | | | |
-* v | | | | | |
-* 0 | v 1 | v | v 2
-* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
-* ^ | ^ | ^ |
-* | | | | | |
-* | | | | `T' <---- 2 bytes for Type
-* | | | |
-* | | '---SNAP--' <-------- 6 bytes for SNAP
-* | |
-* `-IV--' <-------------------- 4 bytes for IV (WEP)
-*
-* SNAP HEADER
-*
-*/
-
-static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
-static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
-
-static inline int ieee80211_put_snap(u8 *data, u16 h_proto)
-{
- struct ieee80211_snap_hdr *snap;
- u8 *oui;
-
- snap = (struct ieee80211_snap_hdr *)data;
- snap->dsap = 0xaa;
- snap->ssap = 0xaa;
- snap->ctrl = 0x03;
-
- if (h_proto == 0x8137 || h_proto == 0x80f3)
- oui = P802_1H_OUI;
- else
- oui = RFC1042_OUI;
- snap->oui[0] = oui[0];
- snap->oui[1] = oui[1];
- snap->oui[2] = oui[2];
-
- *(u16 *)(data + SNAP_SIZE) = htons(h_proto);
-
- return SNAP_SIZE + sizeof(u16);
-}
-
-int ieee80211_encrypt_fragment(struct ieee80211_device *ieee,
- struct sk_buff *frag, int hdr_len)
-{
- struct ieee80211_crypt_data* crypt = ieee->crypt[ieee->tx_keyidx];
- int res;
-
- /*
- * added to care about null crypt condition, to solve that system hangs
- * when shared keys error
- */
- if (!crypt || !crypt->ops)
- return -1;
-
-#ifdef CONFIG_IEEE80211_CRYPT_TKIP
- struct ieee80211_hdr_4addr *header;
-
- if (ieee->tkip_countermeasures &&
- crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
- header = (struct ieee80211_hdr_4addr *)frag->data;
- if (net_ratelimit()) {
- netdev_dbg(ieee->dev, "TKIP countermeasures: dropped "
- "TX packet to %pM\n", header->addr1);
- }
- return -1;
- }
-#endif
- /*
- * To encrypt, frame format is:
- * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes)
- *
- * PR: FIXME: Copied from hostap. Check fragmentation/MSDU/MPDU
- * encryption.
- *
- * Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
- * call both MSDU and MPDU encryption functions from here.
- */
- atomic_inc(&crypt->refcnt);
- res = 0;
- if (crypt->ops->encrypt_msdu)
- res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv);
- if (res == 0 && crypt->ops->encrypt_mpdu)
- res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
-
- atomic_dec(&crypt->refcnt);
- if (res < 0) {
- netdev_info(ieee->dev, "Encryption failed: len=%d.\n", frag->len);
- ieee->ieee_stats.tx_discards++;
- return -1;
- }
-
- return 0;
-}
-
-
-void ieee80211_txb_free(struct ieee80211_txb *txb)
-{
- int i;
- if (unlikely(!txb))
- return;
- for (i = 0; i < txb->nr_frags; i++)
- if (txb->fragments[i])
- dev_kfree_skb_any(txb->fragments[i]);
- kfree(txb);
-}
-
-static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
- gfp_t gfp_mask)
-{
- struct ieee80211_txb *txb;
- int i;
- txb = kmalloc(
- sizeof(struct ieee80211_txb) + (sizeof(u8 *) * nr_frags),
- gfp_mask);
- if (!txb)
- return NULL;
-
- memset(txb, 0, sizeof(struct ieee80211_txb));
- txb->nr_frags = nr_frags;
- txb->frag_size = txb_size;
-
- for (i = 0; i < nr_frags; i++) {
- txb->fragments[i] = dev_alloc_skb(txb_size);
- if (unlikely(!txb->fragments[i])) {
- i--;
- break;
- }
- }
- if (unlikely(i != nr_frags)) {
- while (i >= 0)
- dev_kfree_skb_any(txb->fragments[i--]);
- kfree(txb);
- return NULL;
- }
- return txb;
-}
-
-/*
- * Classify the to-be send data packet
- * Need to acquire the sent queue index.
- */
-static int ieee80211_classify(struct sk_buff *skb,
- struct ieee80211_network *network)
-{
- struct ether_header *eh = (struct ether_header *)skb->data;
- unsigned int wme_UP = 0;
-
- if (!network->QoS_Enable) {
- skb->priority = 0;
- return(wme_UP);
- }
-
- if (eh->ether_type == __constant_htons(ETHERTYPE_IP)) {
- const struct iphdr *ih = (struct iphdr *)(skb->data +
- sizeof(struct ether_header));
- wme_UP = (ih->tos >> 5)&0x07;
- } else if (vlan_tx_tag_present(skb)) {/* vtag packet */
-#ifndef VLAN_PRI_SHIFT
-#define VLAN_PRI_SHIFT 13 /* Shift to find VLAN user priority */
-#define VLAN_PRI_MASK 7 /* Mask for user priority bits in VLAN */
-#endif
- u32 tag = vlan_tx_tag_get(skb);
- wme_UP = (tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK;
- } else if (ETH_P_PAE == ntohs(((struct ethhdr *)skb->data)->h_proto)) {
- wme_UP = 7;
- }
-
- skb->priority = wme_UP;
- return(wme_UP);
-}
-
-/* SKBs are added to the ieee->tx_queue. */
-int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct ieee80211_device *ieee = netdev_priv(dev);
- struct ieee80211_txb *txb = NULL;
- struct ieee80211_hdr_3addrqos *frag_hdr;
- int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size;
- unsigned long flags;
- struct net_device_stats *stats = &ieee->stats;
- int ether_type, encrypt;
- int bytes, fc, qos_ctl, hdr_len;
- struct sk_buff *skb_frag;
- struct ieee80211_hdr_3addrqos header = { /* Ensure zero initialized */
- .duration_id = 0,
- .seq_ctl = 0,
- .qos_ctl = 0
- };
- u8 dest[ETH_ALEN], src[ETH_ALEN];
-
- struct ieee80211_crypt_data* crypt;
-
- spin_lock_irqsave(&ieee->lock, flags);
-
- /*
- * If there is no driver handler to take the TXB, don't bother
- * creating it...
- */
- if ((!ieee->hard_start_xmit &&
- !(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)) ||
- ((!ieee->softmac_data_hard_start_xmit &&
- (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) {
- netdev_warn(ieee->dev, "No xmit handler.\n");
- goto success;
- }
-
- ieee80211_classify(skb,&ieee->current_network);
- if (likely(ieee->raw_tx == 0)){
-
- if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {
- netdev_warn(ieee->dev, "skb too small (%d).\n", skb->len);
- goto success;
- }
-
- ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto);
-
- crypt = ieee->crypt[ieee->tx_keyidx];
-
- encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
- ieee->host_encrypt && crypt && crypt->ops;
-
- if (!encrypt && ieee->ieee802_1x &&
- ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
- stats->tx_dropped++;
- goto success;
- }
-
- #ifdef CONFIG_IEEE80211_DEBUG
- if (crypt && !encrypt && ether_type == ETH_P_PAE) {
- struct eapol *eap = (struct eapol *)(skb->data +
- sizeof(struct ethhdr) - SNAP_SIZE - sizeof(u16));
- IEEE80211_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n",
- eap_get_type(eap->type));
- }
- #endif
-
- /* Save source and destination addresses */
- memcpy(&dest, skb->data, ETH_ALEN);
- memcpy(&src, skb->data+ETH_ALEN, ETH_ALEN);
-
- /* Advance the SKB to the start of the payload */
- skb_pull(skb, sizeof(struct ethhdr));
-
- /* Determine total amount of storage required for TXB packets */
- bytes = skb->len + SNAP_SIZE + sizeof(u16);
-
- if (ieee->current_network.QoS_Enable) {
- if (encrypt)
- fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA |
- IEEE80211_FCTL_WEP;
- else
- fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA;
-
- } else {
- if (encrypt)
- fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
- IEEE80211_FCTL_WEP;
- else
- fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA;
- }
-
- if (ieee->iw_mode == IW_MODE_INFRA) {
- fc |= IEEE80211_FCTL_TODS;
- /* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */
- memcpy(&header.addr1, ieee->current_network.bssid, ETH_ALEN);
- memcpy(&header.addr2, &src, ETH_ALEN);
- memcpy(&header.addr3, &dest, ETH_ALEN);
- } else if (ieee->iw_mode == IW_MODE_ADHOC) {
- /*
- * not From/To DS: Addr1 = DA, Addr2 = SA,
- * Addr3 = BSSID
- */
- memcpy(&header.addr1, dest, ETH_ALEN);
- memcpy(&header.addr2, src, ETH_ALEN);
- memcpy(&header.addr3, ieee->current_network.bssid, ETH_ALEN);
- }
- header.frame_ctl = cpu_to_le16(fc);
-
- /*
- * Determine fragmentation size based on destination (multicast
- * and broadcast are not fragmented)
- */
- if (is_multicast_ether_addr(header.addr1)) {
- frag_size = MAX_FRAG_THRESHOLD;
- qos_ctl = QOS_CTL_NOTCONTAIN_ACK;
- } else {
- /* default:392 */
- frag_size = ieee->fts;
- qos_ctl = 0;
- }
-
- if (ieee->current_network.QoS_Enable) {
- hdr_len = IEEE80211_3ADDR_LEN + 2;
- /* skb->priority is set in the ieee80211_classify() */
- qos_ctl |= skb->priority;
- header.qos_ctl = cpu_to_le16(qos_ctl);
- } else {
- hdr_len = IEEE80211_3ADDR_LEN;
- }
-
- /*
- * Determine amount of payload per fragment. Regardless of if
- * this stack is providing the full 802.11 header, one will
- * eventually be affixed to this fragment -- so we must account
- * for it when determining the amount of payload space.
- */
- bytes_per_frag = frag_size - hdr_len;
- if (ieee->config &
- (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
- bytes_per_frag -= IEEE80211_FCS_LEN;
-
- /* Each fragment may need to have room for encryption pre/postfix */
- if (encrypt)
- bytes_per_frag -= crypt->ops->extra_prefix_len +
- crypt->ops->extra_postfix_len;
-
- /*
- * Number of fragments is the total bytes_per_frag /
- * payload_per_fragment
- */
- nr_frags = bytes / bytes_per_frag;
- bytes_last_frag = bytes % bytes_per_frag;
- if (bytes_last_frag)
- nr_frags++;
- else
- bytes_last_frag = bytes_per_frag;
-
- /*
- * When we allocate the TXB we allocate enough space for the
- * reserve and full fragment bytes (bytes_per_frag doesn't
- * include prefix, postfix, header, FCS, etc.)
- */
- txb = ieee80211_alloc_txb(nr_frags, frag_size, GFP_ATOMIC);
- if (unlikely(!txb)) {
- netdev_warn(ieee->dev, "Could not allocate TXB\n");
- goto failed;
- }
- txb->encrypted = encrypt;
- txb->payload_size = bytes;
-
- for (i = 0; i < nr_frags; i++) {
- skb_frag = txb->fragments[i];
- skb_frag->priority = UP2AC(skb->priority);
- if (encrypt)
- skb_reserve(skb_frag, crypt->ops->extra_prefix_len);
-
- frag_hdr = (struct ieee80211_hdr_3addrqos *)skb_put(
- skb_frag, hdr_len);
- memcpy(frag_hdr, &header, hdr_len);
-
- /*
- * If this is not the last fragment, then add the MOREFRAGS
- * bit to the frame control
- */
- if (i != nr_frags - 1) {
- frag_hdr->frame_ctl = cpu_to_le16(
- fc | IEEE80211_FCTL_MOREFRAGS);
- bytes = bytes_per_frag;
-
- } else {
- /* The last fragment takes the remaining length */
- bytes = bytes_last_frag;
- }
- if (ieee->current_network.QoS_Enable) {
- /*
- * add 1 only indicate to corresponding seq
- * number control 2006/7/12
- */
- frag_hdr->seq_ctl = cpu_to_le16(
- ieee->seq_ctrl[UP2AC(skb->priority)+1]<<4 | i);
- } else {
- frag_hdr->seq_ctl = cpu_to_le16(
- ieee->seq_ctrl[0]<<4 | i);
- }
-
- /* Put a SNAP header on the first fragment */
- if (i == 0) {
- ieee80211_put_snap(
- skb_put(skb_frag, SNAP_SIZE + sizeof(u16)),
- ether_type);
- bytes -= SNAP_SIZE + sizeof(u16);
- }
-
- memcpy(skb_put(skb_frag, bytes), skb->data, bytes);
-
- /* Advance the SKB... */
- skb_pull(skb, bytes);
-
- /*
- * Encryption routine will move the header forward in
- * order to insert the IV between the header and the
- * payload
- */
- if (encrypt)
- ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
- if (ieee->config &
- (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
- skb_put(skb_frag, 4);
- }
- /* Advance sequence number in data frame. */
- if (ieee->current_network.QoS_Enable) {
- if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF)
- ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0;
- else
- ieee->seq_ctrl[UP2AC(skb->priority) + 1]++;
- } else {
- if (ieee->seq_ctrl[0] == 0xFFF)
- ieee->seq_ctrl[0] = 0;
- else
- ieee->seq_ctrl[0]++;
- }
- } else {
- if (unlikely(skb->len < sizeof(struct ieee80211_hdr_3addr))) {
- netdev_warn(ieee->dev, "skb too small (%d).\n", skb->len);
- goto success;
- }
-
- txb = ieee80211_alloc_txb(1, skb->len, GFP_ATOMIC);
- if (!txb) {
- netdev_warn(ieee->dev, "Could not allocate TXB\n");
- goto failed;
- }
-
- txb->encrypted = 0;
- txb->payload_size = skb->len;
- memcpy(skb_put(txb->fragments[0], skb->len), skb->data, skb->len);
- }
-
- success:
- spin_unlock_irqrestore(&ieee->lock, flags);
- dev_kfree_skb_any(skb);
- if (txb) {
- if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) {
- ieee80211_softmac_xmit(txb, ieee);
- } else {
- if ((*ieee->hard_start_xmit)(txb, dev) == 0) {
- stats->tx_packets++;
- stats->tx_bytes += txb->payload_size;
- return NETDEV_TX_OK;
- }
- ieee80211_txb_free(txb);
- }
- }
-
- return NETDEV_TX_OK;
-
- failed:
- spin_unlock_irqrestore(&ieee->lock, flags);
- netif_stop_queue(dev);
- stats->tx_errors++;
- return NETDEV_TX_BUSY;
-
-}
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c
deleted file mode 100644
index 07c3f715a6f5..000000000000
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c
+++ /dev/null
@@ -1,713 +0,0 @@
-/*
- * Copyright(c) 2004 Intel Corporation. All rights reserved.
- *
- * Portions of this file are based on the WEP enablement code provided by the
- * Host AP project hostap-drivers v0.1.3
- * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
- * <jkmaline@cc.hut.fi>
- * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License 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., 59
- * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- */
-
-#include <linux/wireless.h>
-#include <linux/kmod.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/etherdevice.h>
-
-#include "ieee80211.h"
-static const char *ieee80211_modes[] = {
- "?", "a", "b", "ab", "g", "ag", "bg", "abg"
-};
-
-#define MAX_CUSTOM_LEN 64
-static inline char *rtl818x_translate_scan(struct ieee80211_device *ieee,
- char *start, char *stop,
- struct ieee80211_network *network,
- struct iw_request_info *info)
-{
- char custom[MAX_CUSTOM_LEN];
- char *p;
- struct iw_event iwe;
- int i, j;
- u8 max_rate, rate;
-
- /* First entry *MUST* be the AP MAC address */
- iwe.cmd = SIOCGIWAP;
- iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
- ether_addr_copy(iwe.u.ap_addr.sa_data, network->bssid);
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
-
- /* Remaining entries will be displayed in the order we provide them */
-
- /* Add the ESSID */
- iwe.cmd = SIOCGIWESSID;
- iwe.u.data.flags = 1;
- if (network->ssid_len == 0) {
- iwe.u.data.length = sizeof("<hidden>");
- start = iwe_stream_add_point(info, start, stop, &iwe, "<hidden>");
- } else {
- iwe.u.data.length = min_t(u8, network->ssid_len, 32);
- start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
- }
- /* Add the protocol name */
- iwe.cmd = SIOCGIWNAME;
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11%s", ieee80211_modes[network->mode]);
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
-
- /* Add mode */
- iwe.cmd = SIOCGIWMODE;
- if (network->capability &
- (WLAN_CAPABILITY_BSS | WLAN_CAPABILITY_IBSS)) {
- if (network->capability & WLAN_CAPABILITY_BSS)
- iwe.u.mode = IW_MODE_MASTER;
- else
- iwe.u.mode = IW_MODE_ADHOC;
-
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
- }
-
- /* Add frequency/channel */
- iwe.cmd = SIOCGIWFREQ;
- iwe.u.freq.m = network->channel;
- iwe.u.freq.e = 0;
- iwe.u.freq.i = 0;
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
-
- /* Add encryption capability */
- iwe.cmd = SIOCGIWENCODE;
- if (network->capability & WLAN_CAPABILITY_PRIVACY)
- iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
- else
- iwe.u.data.flags = IW_ENCODE_DISABLED;
- iwe.u.data.length = 0;
- start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
-
- /* Add basic and extended rates */
- max_rate = 0;
- p = custom;
- p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
- for (i = 0, j = 0; i < network->rates_len; ) {
- if (j < network->rates_ex_len &&
- ((network->rates_ex[j] & 0x7F) <
- (network->rates[i] & 0x7F)))
- rate = network->rates_ex[j++] & 0x7F;
- else
- rate = network->rates[i++] & 0x7F;
- if (rate > max_rate)
- max_rate = rate;
- p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
- "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
- }
- for (; j < network->rates_ex_len; j++) {
- rate = network->rates_ex[j] & 0x7F;
- p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
- "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
- if (rate > max_rate)
- max_rate = rate;
- }
-
- iwe.cmd = SIOCGIWRATE;
- iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
- iwe.u.bitrate.value = max_rate * 500000;
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_PARAM_LEN);
-
- iwe.cmd = IWEVCUSTOM;
- iwe.u.data.length = p - custom;
- if (iwe.u.data.length)
- start = iwe_stream_add_point(info, start, stop, &iwe, custom);
-
- /* Add quality statistics */
- /* TODO: Fix these values... */
- if (network->stats.signal == 0 || network->stats.rssi == 0)
- netdev_info(ieee->dev, "========>signal:%d, rssi:%d\n",
- network->stats.signal, network->stats.rssi);
- iwe.cmd = IWEVQUAL;
- iwe.u.qual.qual = network->stats.signalstrength;
- iwe.u.qual.level = network->stats.signal;
- iwe.u.qual.noise = network->stats.noise;
- iwe.u.qual.updated = network->stats.mask & IEEE80211_STATMASK_WEMASK;
- if (!(network->stats.mask & IEEE80211_STATMASK_RSSI))
- iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
- if (!(network->stats.mask & IEEE80211_STATMASK_NOISE))
- iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
- if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL))
- iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
- iwe.u.qual.updated = 7;
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
-
- iwe.cmd = IWEVCUSTOM;
- p = custom;
-
- iwe.u.data.length = p - custom;
- if (iwe.u.data.length)
- start = iwe_stream_add_point(info, start, stop, &iwe, custom);
-
- memset(&iwe, 0, sizeof(iwe));
- if (network->wpa_ie_len) {
- char buf[MAX_WPA_IE_LEN];
- memcpy(buf, network->wpa_ie, network->wpa_ie_len);
- iwe.cmd = IWEVGENIE;
- iwe.u.data.length = network->wpa_ie_len;
- start = iwe_stream_add_point(info, start, stop, &iwe, buf);
- }
-
- memset(&iwe, 0, sizeof(iwe));
- if (network->rsn_ie_len) {
- char buf[MAX_WPA_IE_LEN];
- memcpy(buf, network->rsn_ie, network->rsn_ie_len);
- iwe.cmd = IWEVGENIE;
- iwe.u.data.length = network->rsn_ie_len;
- start = iwe_stream_add_point(info, start, stop, &iwe, buf);
- }
-
- /* Add EXTRA: Age to display seconds since last beacon/probe response
- * for given network.
- */
- iwe.cmd = IWEVCUSTOM;
- p = custom;
- p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
- " Last beacon: %lums ago", (jiffies - network->last_scanned) / (HZ / 100));
- iwe.u.data.length = p - custom;
- if (iwe.u.data.length)
- start = iwe_stream_add_point(info, start, stop, &iwe, custom);
-
- return start;
-}
-
-int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct ieee80211_network *network;
- unsigned long flags;
- int err = 0;
- char *ev = extra;
- char *stop = ev + wrqu->data.length;
- int i = 0;
-
- IEEE80211_DEBUG_WX("Getting scan\n");
- down(&ieee->wx_sem);
- spin_lock_irqsave(&ieee->lock, flags);
-
- if (!ieee->bHwRadioOff) {
- list_for_each_entry(network, &ieee->network_list, list) {
- i++;
-
- if ((stop-ev) < 200) {
- err = -E2BIG;
- break;
- }
- if (ieee->scan_age == 0 ||
- time_after(network->last_scanned + ieee->scan_age, jiffies)) {
- ev = rtl818x_translate_scan(ieee, ev, stop, network, info);
- } else
- IEEE80211_DEBUG_SCAN(
- "Not showing network '%s ("
- "%pM)' due to age (%lums).\n",
- escape_essid(network->ssid,
- network->ssid_len),
- network->bssid,
- (jiffies - network->last_scanned) / (HZ / 100));
- }
- }
- spin_unlock_irqrestore(&ieee->lock, flags);
- up(&ieee->wx_sem);
- wrqu->data.length = ev - extra;
- wrqu->data.flags = 0;
- IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
-
- return err;
-}
-
-int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *keybuf)
-{
- struct iw_point *erq = &(wrqu->encoding);
- struct net_device *dev = ieee->dev;
- struct ieee80211_security sec = {
- .flags = 0
- };
- int i, key, key_provided, len;
- struct ieee80211_crypt_data **crypt;
-
- IEEE80211_DEBUG_WX("SET_ENCODE\n");
-
- key = erq->flags & IW_ENCODE_INDEX;
- if (key) {
- if (key > WEP_KEYS)
- return -EINVAL;
- key--;
- key_provided = 1;
- } else {
- key_provided = 0;
- key = ieee->tx_keyidx;
- }
-
- IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
- "provided" : "default");
-
- crypt = &ieee->crypt[key];
-
- if (erq->flags & IW_ENCODE_DISABLED) {
- if (key_provided && *crypt) {
- IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
- key);
- ieee80211_crypt_delayed_deinit(ieee, crypt);
- } else
- IEEE80211_DEBUG_WX("Disabling encryption.\n");
-
- /* Check all the keys to see if any are still configured,
- * and if no key index was provided, de-init them all.
- */
- for (i = 0; i < WEP_KEYS; i++) {
- if (ieee->crypt[i] != NULL) {
- if (key_provided)
- break;
- ieee80211_crypt_delayed_deinit(
- ieee, &ieee->crypt[i]);
- }
- }
-
- if (i == WEP_KEYS) {
- sec.enabled = 0;
- sec.level = SEC_LEVEL_0;
- sec.flags |= SEC_ENABLED | SEC_LEVEL;
- }
-
- goto done;
- }
-
- sec.enabled = 1;
- sec.flags |= SEC_ENABLED;
-
- if (*crypt != NULL && (*crypt)->ops != NULL &&
- strcmp((*crypt)->ops->name, "WEP") != 0) {
- /* changing to use WEP; deinit previously used algorithm
- * on this key.
- */
- ieee80211_crypt_delayed_deinit(ieee, crypt);
- }
-
- if (*crypt == NULL) {
- struct ieee80211_crypt_data *new_crypt;
-
- /* take WEP into use */
- new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
- GFP_KERNEL);
- if (new_crypt == NULL)
- return -ENOMEM;
- new_crypt->ops = ieee80211_get_crypto_ops("WEP");
- if (!new_crypt->ops)
- new_crypt->ops = ieee80211_get_crypto_ops("WEP");
-
- if (new_crypt->ops)
- new_crypt->priv = new_crypt->ops->init(key);
-
- if (!new_crypt->ops || !new_crypt->priv) {
- kfree(new_crypt);
- new_crypt = NULL;
-
- netdev_warn(ieee->dev,
- "could not initialize WEP: load module ieee80211_crypt_wep\n");
- return -EOPNOTSUPP;
- }
- *crypt = new_crypt;
- }
-
- /* If a new key was provided, set it up */
- if (erq->length > 0) {
- len = erq->length <= 5 ? 5 : 13;
- memcpy(sec.keys[key], keybuf, erq->length);
- if (len > erq->length)
- memset(sec.keys[key] + erq->length, 0,
- len - erq->length);
- IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
- key, escape_essid(sec.keys[key], len),
- erq->length, len);
- sec.key_sizes[key] = len;
- (*crypt)->ops->set_key(sec.keys[key], len, NULL,
- (*crypt)->priv);
- sec.flags |= (1 << key);
- /* This ensures a key will be activated if no key is
- * explicitly set.
- */
- if (key == sec.active_key)
- sec.flags |= SEC_ACTIVE_KEY;
- ieee->tx_keyidx = key;
- } else {
- len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
- NULL, (*crypt)->priv);
- if (len == 0) {
- /* Set a default key of all 0 */
- IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
- key);
- memset(sec.keys[key], 0, 13);
- (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
- (*crypt)->priv);
- sec.key_sizes[key] = 13;
- sec.flags |= (1 << key);
- }
-
- /* No key data - just set the default TX key index */
- if (key_provided) {
- IEEE80211_DEBUG_WX(
- "Setting key %d to default Tx key.\n", key);
- ieee->tx_keyidx = key;
- sec.active_key = key;
- sec.flags |= SEC_ACTIVE_KEY;
- }
- }
-
- done:
- ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
- sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
- sec.flags |= SEC_AUTH_MODE;
- IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
- "OPEN" : "SHARED KEY");
-
- /* For now we just support WEP, so only set that security level...
- * TODO: When WPA is added this is one place that needs to change
- */
- sec.flags |= SEC_LEVEL;
- sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
-
- if (ieee->set_security)
- ieee->set_security(dev, &sec);
-
- /* Do not reset port if card is in Managed mode since resetting will
- * generate new IEEE 802.11 authentication which may end up in looping
- * with IEEE 802.1X. If your hardware requires a reset after WEP
- * configuration (for example... Prism2), implement the reset_port in
- * the callbacks structures used to initialize the 802.11 stack.
- */
- if (ieee->reset_on_keychange &&
- ieee->iw_mode != IW_MODE_INFRA &&
- ieee->reset_port && ieee->reset_port(dev)) {
- netdev_dbg(ieee->dev, "reset_port failed\n");
- return -EINVAL;
- }
- return 0;
-}
-
-int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *keybuf)
-{
- struct iw_point *erq = &(wrqu->encoding);
- int len, key;
- struct ieee80211_crypt_data *crypt;
-
- IEEE80211_DEBUG_WX("GET_ENCODE\n");
-
- if (ieee->iw_mode == IW_MODE_MONITOR)
- return -1;
-
- key = erq->flags & IW_ENCODE_INDEX;
- if (key) {
- if (key > WEP_KEYS)
- return -EINVAL;
- key--;
- } else
- key = ieee->tx_keyidx;
-
- crypt = ieee->crypt[key];
- erq->flags = key + 1;
-
- if (crypt == NULL || crypt->ops == NULL) {
- erq->length = 0;
- erq->flags |= IW_ENCODE_DISABLED;
- return 0;
- }
-
- if (strcmp(crypt->ops->name, "WEP") != 0) {
- /* only WEP is supported with wireless extensions, so just
- * report that encryption is used.
- */
- erq->length = 0;
- erq->flags |= IW_ENCODE_ENABLED;
- return 0;
- }
-
- len = crypt->ops->get_key(keybuf, WEP_KEY_LEN, NULL, crypt->priv);
- erq->length = (len >= 0 ? len : 0);
-
- erq->flags |= IW_ENCODE_ENABLED;
-
- if (ieee->open_wep)
- erq->flags |= IW_ENCODE_OPEN;
- else
- erq->flags |= IW_ENCODE_RESTRICTED;
-
- return 0;
-}
-
-int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct net_device *dev = ieee->dev;
- struct iw_point *encoding = &wrqu->encoding;
- struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
- int i, idx, ret = 0;
- int group_key = 0;
- const char *alg;
- struct ieee80211_crypto_ops *ops;
- struct ieee80211_crypt_data **crypt;
-
- struct ieee80211_security sec = {
- .flags = 0,
- };
- idx = encoding->flags & IW_ENCODE_INDEX;
- if (idx) {
- if (idx < 1 || idx > WEP_KEYS)
- return -EINVAL;
- idx--;
- } else
- idx = ieee->tx_keyidx;
-
- if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
- crypt = &ieee->crypt[idx];
- group_key = 1;
- } else {
- /* some Cisco APs use idx>0 for unicast in dynamic WEP */
- if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
- return -EINVAL;
- if (ieee->iw_mode == IW_MODE_INFRA)
- crypt = &ieee->crypt[idx];
- else
- return -EINVAL;
- }
-
- sec.flags |= SEC_ENABLED;
- if ((encoding->flags & IW_ENCODE_DISABLED) ||
- ext->alg == IW_ENCODE_ALG_NONE) {
- if (*crypt)
- ieee80211_crypt_delayed_deinit(ieee, crypt);
-
- for (i = 0; i < WEP_KEYS; i++)
- if (ieee->crypt[i] != NULL)
- break;
-
- if (i == WEP_KEYS) {
- sec.enabled = 0;
- sec.level = SEC_LEVEL_0;
- sec.flags |= SEC_LEVEL;
- }
- goto done;
- }
-
- sec.enabled = 1;
-
- switch (ext->alg) {
- case IW_ENCODE_ALG_WEP:
- alg = "WEP";
- break;
- case IW_ENCODE_ALG_TKIP:
- alg = "TKIP";
- break;
- case IW_ENCODE_ALG_CCMP:
- alg = "CCMP";
- break;
- default:
- IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
- dev->name, ext->alg);
- ret = -EINVAL;
- goto done;
- }
-
- ops = ieee80211_get_crypto_ops(alg);
- if (ops == NULL)
- ops = ieee80211_get_crypto_ops(alg);
- if (ops == NULL) {
- IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
- dev->name, ext->alg);
- netdev_err(ieee->dev, "========>unknown crypto alg %d\n",
- ext->alg);
- ret = -EINVAL;
- goto done;
- }
-
- if (*crypt == NULL || (*crypt)->ops != ops) {
- struct ieee80211_crypt_data *new_crypt;
-
- ieee80211_crypt_delayed_deinit(ieee, crypt);
-
- new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
- if (new_crypt == NULL) {
- ret = -ENOMEM;
- goto done;
- }
- new_crypt->ops = ops;
- if (new_crypt->ops)
- new_crypt->priv = new_crypt->ops->init(idx);
- if (new_crypt->priv == NULL) {
- kfree(new_crypt);
- ret = -EINVAL;
- goto done;
- }
- *crypt = new_crypt;
-
- }
-
- if (ext->key_len > 0 && (*crypt)->ops->set_key &&
- (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
- (*crypt)->priv) < 0) {
- IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
- netdev_err(ieee->dev, "key setting failed\n");
- ret = -EINVAL;
- goto done;
- }
-#if 1
- if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
- ieee->tx_keyidx = idx;
- sec.active_key = idx;
- sec.flags |= SEC_ACTIVE_KEY;
- }
-
- if (ext->alg != IW_ENCODE_ALG_NONE) {
- memcpy(sec.keys[idx], ext->key, ext->key_len);
- sec.key_sizes[idx] = ext->key_len;
- sec.flags |= (1 << idx);
- if (ext->alg == IW_ENCODE_ALG_WEP) {
- sec.flags |= SEC_LEVEL;
- sec.level = SEC_LEVEL_1;
- } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
- sec.flags |= SEC_LEVEL;
- sec.level = SEC_LEVEL_2;
- } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
- sec.flags |= SEC_LEVEL;
- sec.level = SEC_LEVEL_3;
- }
- /* Don't set sec level for group keys. */
- if (group_key)
- sec.flags &= ~SEC_LEVEL;
- }
-#endif
-done:
- if (ieee->set_security)
- ieee->set_security(ieee->dev, &sec);
-
- if (ieee->reset_on_keychange &&
- ieee->iw_mode != IW_MODE_INFRA &&
- ieee->reset_port && ieee->reset_port(dev)) {
- IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
- return -EINVAL;
- }
-
- return ret;
-}
-
-int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct iw_mlme *mlme = (struct iw_mlme *) extra;
-#if 1
- switch (mlme->cmd) {
- case IW_MLME_DEAUTH:
- case IW_MLME_DISASSOC:
- ieee80211_disassociate(ieee);
- break;
- default:
- return -EOPNOTSUPP;
- }
-#endif
- return 0;
-}
-
-int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- struct iw_param *data, char *extra)
-{
- switch (data->flags & IW_AUTH_INDEX) {
- case IW_AUTH_WPA_VERSION:
- /* need to support wpa2 here */
- break;
- case IW_AUTH_CIPHER_PAIRWISE:
- case IW_AUTH_CIPHER_GROUP:
- case IW_AUTH_KEY_MGMT:
- /* Host AP driver does not use these parameters and allows
- * wpa_supplicant to control them internally.
- */
- break;
- case IW_AUTH_TKIP_COUNTERMEASURES:
- ieee->tkip_countermeasures = data->value;
- break;
- case IW_AUTH_DROP_UNENCRYPTED:
- ieee->drop_unencrypted = data->value;
- break;
-
- case IW_AUTH_80211_AUTH_ALG:
- ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM) ? 1 : 0;
- break;
-
-#if 1
- case IW_AUTH_WPA_ENABLED:
- ieee->wpa_enabled = (data->value) ? 1 : 0;
- break;
-
-#endif
- case IW_AUTH_RX_UNENCRYPTED_EAPOL:
- ieee->ieee802_1x = data->value;
- break;
- case IW_AUTH_PRIVACY_INVOKED:
- ieee->privacy_invoked = data->value;
- break;
- default:
- return -EOPNOTSUPP;
- }
- return 0;
-}
-
-#if 1
-int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
-{
- u8 *buf = NULL;
-
- if (len > MAX_WPA_IE_LEN || (len && ie == NULL)) {
- netdev_err(ieee->dev, "return error out, len:%zu\n", len);
- return -EINVAL;
- }
-
- if (len) {
- if (len != ie[1]+2) {
- netdev_err(ieee->dev, "len:%zu, ie:%d\n", len, ie[1]);
- return -EINVAL;
- }
- buf = kmemdup(ie, len, GFP_KERNEL);
- if (buf == NULL)
- return -ENOMEM;
- kfree(ieee->wpa_ie);
- ieee->wpa_ie = buf;
- ieee->wpa_ie_len = len;
- } else {
- kfree(ieee->wpa_ie);
- ieee->wpa_ie = NULL;
- ieee->wpa_ie_len = 0;
- }
-
- return 0;
-
-}
-#endif
diff --git a/drivers/staging/rtl8187se/r8180.h b/drivers/staging/rtl8187se/r8180.h
deleted file mode 100644
index 9f931dba1d82..000000000000
--- a/drivers/staging/rtl8187se/r8180.h
+++ /dev/null
@@ -1,640 +0,0 @@
-/*
- * This is part of rtl8180 OpenSource driver.
- * Copyright (C) Andrea Merello 2004-2005 <andrea.merello@gmail.com>
- * Released under the terms of GPL (General Public Licence)
- *
- * Parts of this driver are based on the GPL part of the official realtek driver
- *
- * Parts of this driver are based on the rtl8180 driver skeleton from Patric
- * Schenke & Andres Salomon
- *
- * Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver
- *
- * We want to thanks the Authors of those projects and the Ndiswrapper project
- * Authors.
- */
-
-#ifndef R8180H
-#define R8180H
-
-#include <linux/interrupt.h>
-
-#define RTL8180_MODULE_NAME "r8180"
-#define DMESG(x, a...) printk(KERN_INFO RTL8180_MODULE_NAME ": " x "\n", ## a)
-#define DMESGW(x, a...) printk(KERN_WARNING RTL8180_MODULE_NAME ": WW:" x "\n", ## a)
-#define DMESGE(x, a...) printk(KERN_WARNING RTL8180_MODULE_NAME ": EE:" x "\n", ## a)
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/netdevice.h>
-#include <linux/pci.h>
-#include <linux/etherdevice.h>
-#include <linux/delay.h>
-#include <linux/rtnetlink.h> /* for rtnl_lock() */
-#include <linux/wireless.h>
-#include <linux/timer.h>
-#include <linux/proc_fs.h> /* Necessary because we use the proc fs. */
-#include <linux/if_arp.h>
-#include "ieee80211/ieee80211.h"
-#include <asm/io.h>
-
-#define EPROM_93c46 0
-#define EPROM_93c56 1
-
-#define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 30)
-
-#define DEFAULT_FRAG_THRESHOLD 2342U
-#define MIN_FRAG_THRESHOLD 256U
-#define DEFAULT_RTS_THRESHOLD 2342U
-#define MIN_RTS_THRESHOLD 0U
-#define MAX_RTS_THRESHOLD 2342U
-#define DEFAULT_BEACONINTERVAL 0x64U
-
-#define DEFAULT_RETRY_RTS 7
-#define DEFAULT_RETRY_DATA 7
-
-#define BEACON_QUEUE 6
-
-#define aSifsTime 10
-
-#define sCrcLng 4
-#define sAckCtsLng 112 /* bits in ACK and CTS frames. */
-/* +by amy 080312. */
-#define RATE_ADAPTIVE_TIMER_PERIOD 300
-
-enum wireless_mode {
- WIRELESS_MODE_UNKNOWN = 0x00,
- WIRELESS_MODE_A = 0x01,
- WIRELESS_MODE_B = 0x02,
- WIRELESS_MODE_G = 0x04,
- WIRELESS_MODE_AUTO = 0x08,
-};
-
-struct chnl_access_setting {
- u16 sifs_timer;
- u16 difs_timer;
- u16 slot_time_timer;
- u16 eifs_timer;
- u16 cwmin_index;
- u16 cwmax_index;
-};
-
-enum nic_t {
- NIC_8185 = 1,
- NIC_8185B
-};
-
-typedef u32 AC_CODING;
-#define AC0_BE 0 /* ACI: 0x00 */ /* Best Effort. */
-#define AC1_BK 1 /* ACI: 0x01 */ /* Background. */
-#define AC2_VI 2 /* ACI: 0x10 */ /* Video. */
-#define AC3_VO 3 /* ACI: 0x11 */ /* Voice. */
-#define AC_MAX 4 /* Max: define total number; Should not to be used as a real
- * enum.
- */
-
-/*
- * ECWmin/ECWmax field.
- * Ref: WMM spec 2.2.2: WME Parameter Element, p.13.
- */
-typedef union _ECW {
- u8 charData;
- struct {
- u8 ECWmin:4;
- u8 ECWmax:4;
- } f; /* Field */
-} ECW, *PECW;
-
-/*
- * ACI/AIFSN Field. Ref: WMM spec 2.2.2: WME Parameter Element, p.12.
- */
-typedef union _ACI_AIFSN {
- u8 charData;
-
- struct {
- u8 AIFSN:4;
- u8 ACM:1;
- u8 ACI:2;
- u8 Reserved:1;
- } f; /* Field */
-} ACI_AIFSN, *PACI_AIFSN;
-
-/*
- * AC Parameters Record Format.
- * Ref: WMM spec 2.2.2: WME Parameter Element, p.12.
- */
-typedef union _AC_PARAM {
- u32 longData;
- u8 charData[4];
-
- struct {
- ACI_AIFSN AciAifsn;
- ECW Ecw;
- u16 TXOPLimit;
- } f; /* Field */
-} AC_PARAM, *PAC_PARAM;
-
-struct buffer {
- struct buffer *next;
- u32 *buf;
- dma_addr_t dma;
-};
-
-/* YJ,modified,080828. */
-struct stats {
- unsigned long txrdu;
- unsigned long rxrdu;
- unsigned long rxnolast;
- unsigned long rxnodata;
- unsigned long rxnopointer;
- unsigned long txnperr;
- unsigned long txresumed;
- unsigned long rxerr;
- unsigned long rxoverflow;
- unsigned long rxint;
- unsigned long txbkpokint;
- unsigned long txbepoking;
- unsigned long txbkperr;
- unsigned long txbeperr;
- unsigned long txnpokint;
- unsigned long txhpokint;
- unsigned long txhperr;
- unsigned long ints;
- unsigned long shints;
- unsigned long txoverflow;
- unsigned long rxdmafail;
- unsigned long txbeacon;
- unsigned long txbeaconerr;
- unsigned long txlpokint;
- unsigned long txlperr;
- unsigned long txretry; /* retry number tony 20060601 */
- unsigned long rxcrcerrmin; /* crc error (0-500) */
- unsigned long rxcrcerrmid; /* crc error (500-1000) */
- unsigned long rxcrcerrmax; /* crc error (>1000) */
- unsigned long rxicverr; /* ICV error */
-};
-
-#define MAX_LD_SLOT_NUM 10
-#define KEEP_ALIVE_INTERVAL 20 /* in seconds. */
-#define CHECK_FOR_HANG_PERIOD 2 /* be equal to watchdog check time. */
-#define DEFAULT_KEEP_ALIVE_LEVEL 1
-#define DEFAULT_SLOT_NUM 2
-#define POWER_PROFILE_AC 0
-#define POWER_PROFILE_BATTERY 1
-
-struct link_detect_t {
- u32 rx_frame_num[MAX_LD_SLOT_NUM]; /* number of Rx Frame.
- * CheckForHang_period to determine
- * link status.
- */
- u16 slot_num; /* number of CheckForHang period to determine link status,
- * default is 2.
- */
- u16 slot_index;
- u32 num_tx_ok_in_period; /* number of packet transmitted during
- * CheckForHang.
- */
- u32 num_rx_ok_in_period; /* number of packet received during
- * CheckForHang.
- */
- u8 idle_count; /* (KEEP_ALIVE_INTERVAL / CHECK_FOR_HANG_PERIOD) */
- u32 last_num_tx_unicast;
- u32 last_num_rx_unicast;
-
- bool b_busy_traffic; /* when it is set to 1, UI cann't scan at will. */
-};
-
-/* YJ,modified,080828,end */
-
-/* by amy for led
- * ==========================================================================
- * LED customization.
- * ==========================================================================
- */
-enum led_strategy_8185 {
- SW_LED_MODE0,
- SW_LED_MODE1,
- HW_LED, /* HW control 2 LEDs, LED0 and LED1 (there are 4 different
- * control modes). */
-};
-
-enum rt_rf_power_state {
- RF_ON,
- RF_SLEEP,
- RF_OFF
-};
-
-enum _ReasonCode {
- unspec_reason = 0x1,
- auth_not_valid = 0x2,
- deauth_lv_ss = 0x3,
- inactivity = 0x4,
- ap_overload = 0x5,
- class2_err = 0x6,
- class3_err = 0x7,
- disas_lv_ss = 0x8,
- asoc_not_auth = 0x9,
-
- /* ----MIC_CHECK */
- mic_failure = 0xe,
- /* ----END MIC_CHECK */
-
- /* Reason code defined in 802.11i D10.0 p.28. */
- invalid_IE = 0x0d,
- four_way_tmout = 0x0f,
- two_way_tmout = 0x10,
- IE_dismatch = 0x11,
- invalid_Gcipher = 0x12,
- invalid_Pcipher = 0x13,
- invalid_AKMP = 0x14,
- unsup_RSNIEver = 0x15,
- invalid_RSNIE = 0x16,
- auth_802_1x_fail = 0x17,
- ciper_reject = 0x18,
-
- /* Reason code defined in 7.3.1.7, 802.1e D13.0, p.42. Added by Annie,
- * 2005-11-15.
- */
- QoS_unspec = 0x20, /* 32 */
- QAP_bandwidth = 0x21, /* 33 */
- poor_condition = 0x22, /* 34 */
- no_facility = 0x23, /* 35 */
- /* Where is 36??? */
- req_declined = 0x25, /* 37 */
- invalid_param = 0x26, /* 38 */
- req_not_honored = 0x27, /* 39 */
- TS_not_created = 0x2F, /* 47 */
- DL_not_allowed = 0x30, /* 48 */
- dest_not_exist = 0x31, /* 49 */
- dest_not_QSTA = 0x32, /* 50 */
-};
-
-enum rt_ps_mode {
- ACTIVE, /* Active/Continuous access. */
- MAX_PS, /* Max power save mode. */
- FAST_PS /* Fast power save mode. */
-};
-
-/* by amy for power save. */
-struct r8180_priv {
- struct pci_dev *pdev;
-
- short epromtype;
- int irq;
- struct ieee80211_device *ieee80211;
-
- short plcp_preamble_mode; /* 0:auto 1:short 2:long */
-
- spinlock_t irq_th_lock;
- spinlock_t tx_lock;
- spinlock_t ps_lock;
- spinlock_t rf_ps_lock;
-
- u16 irq_mask;
- short irq_enabled;
- struct net_device *dev;
- short chan;
- short sens;
- short max_sens;
- u8 chtxpwr[15]; /* channels from 1 to 14, 0 not used. */
- u8 chtxpwr_ofdm[15]; /* channels from 1 to 14, 0 not used. */
- u8 channel_plan; /* it's the channel plan index. */
- short up;
- short crcmon; /* if 1 allow bad crc frame reception in monitor mode. */
-
- struct timer_list scan_timer;
- spinlock_t scan_lock;
- u8 active_probe;
- struct semaphore wx_sem;
- short hw_wep;
-
- short digphy;
- short antb;
- short diversity;
- u32 key0[4];
- short (*rf_set_sens)(struct net_device *dev, short sens);
- void (*rf_set_chan)(struct net_device *dev, short ch);
- void (*rf_close)(struct net_device *dev);
- void (*rf_init)(struct net_device *dev);
- void (*rf_sleep)(struct net_device *dev);
- void (*rf_wakeup)(struct net_device *dev);
- /* short rate; */
- short promisc;
- /* stats */
- struct stats stats;
- struct link_detect_t link_detect; /* YJ,add,080828 */
- struct iw_statistics wstats;
-
- /* RX stuff. */
- u32 *rxring;
- u32 *rxringtail;
- dma_addr_t rxringdma;
- struct buffer *rxbuffer;
- struct buffer *rxbufferhead;
- int rxringcount;
- u16 rxbuffersize;
-
- struct sk_buff *rx_skb;
-
- short rx_skb_complete;
-
- u32 rx_prevlen;
-
- u32 *txmapring;
- u32 *txbkpring;
- u32 *txbepring;
- u32 *txvipring;
- u32 *txvopring;
- u32 *txhpring;
- dma_addr_t txmapringdma;
- dma_addr_t txbkpringdma;
- dma_addr_t txbepringdma;
- dma_addr_t txvipringdma;
- dma_addr_t txvopringdma;
- dma_addr_t txhpringdma;
- u32 *txmapringtail;
- u32 *txbkpringtail;
- u32 *txbepringtail;
- u32 *txvipringtail;
- u32 *txvopringtail;
- u32 *txhpringtail;
- u32 *txmapringhead;
- u32 *txbkpringhead;
- u32 *txbepringhead;
- u32 *txvipringhead;
- u32 *txvopringhead;
- u32 *txhpringhead;
- struct buffer *txmapbufs;
- struct buffer *txbkpbufs;
- struct buffer *txbepbufs;
- struct buffer *txvipbufs;
- struct buffer *txvopbufs;
- struct buffer *txhpbufs;
- struct buffer *txmapbufstail;
- struct buffer *txbkpbufstail;
- struct buffer *txbepbufstail;
- struct buffer *txvipbufstail;
- struct buffer *txvopbufstail;
- struct buffer *txhpbufstail;
-
- int txringcount;
- int txbuffsize;
- struct tasklet_struct irq_rx_tasklet;
- u8 dma_poll_mask;
-
- /* adhoc/master mode stuff. */
- u32 *txbeaconringtail;
- dma_addr_t txbeaconringdma;
- u32 *txbeaconring;
- int txbeaconcount;
- struct buffer *txbeaconbufs;
- struct buffer *txbeaconbufstail;
-
- u8 retry_data;
- u8 retry_rts;
- u16 rts;
-
- /* by amy for led. */
- enum led_strategy_8185 led_strategy;
- /* by amy for led. */
-
- /* by amy for power save. */
- struct timer_list watch_dog_timer;
- bool bInactivePs;
- bool bSwRfProcessing;
- enum rt_rf_power_state eInactivePowerState;
- enum rt_rf_power_state eRFPowerState;
- u32 RfOffReason;
- bool RFChangeInProgress;
- bool SetRFPowerStateInProgress;
- u8 RFProgType;
- bool bLeisurePs;
- enum rt_ps_mode dot11PowerSaveMode;
- u8 TxPollingTimes;
-
- bool bApBufOurFrame; /* TRUE if AP buffer our unicast data , we will
- * keep eAwake until receive data or timeout.
- */
- u8 WaitBufDataBcnCount;
- u8 WaitBufDataTimeOut;
-
- /* by amy for power save. */
- /* by amy for antenna. */
- u8 EEPROMSwAntennaDiversity;
- bool EEPROMDefaultAntenna1;
- u8 RegSwAntennaDiversityMechanism;
- bool bSwAntennaDiverity;
- u8 RegDefaultAntenna;
- bool bDefaultAntenna1;
- u8 SignalStrength;
- long Stats_SignalStrength;
- long LastSignalStrengthInPercent; /* In percentage, used for smoothing,
- * e.g. Moving Average.
- */
- u8 SignalQuality; /* in 0-100 index. */
- long Stats_SignalQuality;
- long RecvSignalPower; /* in dBm. */
- long Stats_RecvSignalPower;
- u8 LastRxPktAntenna; /* +by amy 080312 Antenna which received the lasted
- * packet. 0: Aux, 1:Main. Added by Roger,
- * 2008.01.25.
- */
- u32 AdRxOkCnt;
- long AdRxSignalStrength;
- u8 CurrAntennaIndex; /* Index to current Antenna (both Tx and Rx). */
- u8 AdTickCount; /* Times of SwAntennaDiversityTimer happened. */
- u8 AdCheckPeriod; /* # of period SwAntennaDiversityTimer to check Rx
- * signal strength for SW Antenna Diversity.
- */
- u8 AdMinCheckPeriod; /* Min value of AdCheckPeriod. */
- u8 AdMaxCheckPeriod; /* Max value of AdCheckPeriod. */
- long AdRxSsThreshold; /* Signal strength threshold to switch antenna. */
- long AdMaxRxSsThreshold; /* Max value of AdRxSsThreshold. */
- bool bAdSwitchedChecking; /* TRUE if we shall shall check Rx signal
- * strength for last time switching antenna.
- */
- long AdRxSsBeforeSwitched; /* Rx signal strength before we switched
- * antenna.
- */
- struct timer_list SwAntennaDiversityTimer;
- /* by amy for antenna {by amy 080312 */
-
- /* Crystal calibration. Added by Roger, 2007.12.11. */
-
- bool bXtalCalibration; /* Crystal calibration.*/
- u8 XtalCal_Xin; /* Crystal calibration for Xin. 0~7.5pF */
- u8 XtalCal_Xout; /* Crystal calibration for Xout. 0~7.5pF */
-
- /* Tx power tracking with thermal meter indication.
- * Added by Roger, 2007.12.11.
- */
-
- bool bTxPowerTrack; /* Tx Power tracking. */
- u8 ThermalMeter; /* Thermal meter reference indication. */
-
- /* Dynamic Initial Gain Adjustment Mechanism. Added by Bruce,
- * 2007-02-14.
- */
- bool bDigMechanism; /* TRUE if DIG is enabled, FALSE ow. */
- bool bRegHighPowerMechanism; /* For High Power Mechanism. 061010,
- * by rcnjko.
- */
- u32 FalseAlarmRegValue;
- u8 RegDigOfdmFaUpTh; /* Upper threshold of OFDM false alarm, which is
- * used in DIG.
- */
- u8 DIG_NumberFallbackVote;
- u8 DIG_NumberUpgradeVote;
- /* For HW antenna diversity, added by Roger, 2008.01.30. */
- u32 AdMainAntennaRxOkCnt; /* Main antenna Rx OK count. */
- u32 AdAuxAntennaRxOkCnt; /* Aux antenna Rx OK count. */
- bool bHWAdSwitched; /* TRUE if we has switched default antenna by HW
- * evaluation.
- */
- /* RF High Power upper/lower threshold. */
- u8 RegHiPwrUpperTh;
- u8 RegHiPwrLowerTh;
- /* RF RSSI High Power upper/lower Threshold. */
- u8 RegRSSIHiPwrUpperTh;
- u8 RegRSSIHiPwrLowerTh;
- /* Current CCK RSSI value to determine CCK high power, asked by SD3 DZ,
- * by Bruce, 2007-04-12.
- */
- u8 CurCCKRSSI;
- bool bCurCCKPkt;
- /* High Power Mechanism. Added by amy, 080312. */
- bool bToUpdateTxPwr;
- long UndecoratedSmoothedSS;
- long UndecoratedSmoothedRxPower;
- u8 RSSI;
- char RxPower;
- u8 InitialGain;
- /* For adjust Dig Threshold during Legacy/Leisure Power Save Mode. */
- u32 DozePeriodInPast2Sec;
- /* Don't access BB/RF under disable PLL situation. */
- u8 InitialGainBackUp;
- u8 RegBModeGainStage;
- /* by amy for rate adaptive */
- struct timer_list rateadapter_timer;
- u32 RateAdaptivePeriod;
- bool bEnhanceTxPwr;
- bool bUpdateARFR;
- int ForcedDataRate; /* Force Data Rate. 0: Auto, 0x02: 1M ~ 0x6C: 54M.)
- */
- u32 NumTxUnicast; /* YJ,add,080828,for keep alive. */
- u8 keepAliveLevel; /*YJ,add,080828,for KeepAlive. */
- unsigned long NumTxOkTotal;
- u16 LastRetryCnt;
- u16 LastRetryRate;
- unsigned long LastTxokCnt;
- unsigned long LastRxokCnt;
- u16 CurrRetryCnt;
- unsigned long LastTxOKBytes;
- unsigned long NumTxOkBytesTotal;
- u8 LastFailTxRate;
- long LastFailTxRateSS;
- u8 FailTxRateCount;
- u32 LastTxThroughput;
- /* for up rate. */
- unsigned short bTryuping;
- u8 CurrTxRate; /* the rate before up. */
- u16 CurrRetryRate;
- u16 TryupingCount;
- u8 TryDownCountLowData;
- u8 TryupingCountNoData;
-
- u8 CurrentOperaRate;
- struct work_struct reset_wq;
- struct work_struct watch_dog_wq;
- short ack_tx_to_ieee;
-
- u8 dma_poll_stop_mask;
-
- u16 ShortRetryLimit;
- u16 LongRetryLimit;
- u16 EarlyRxThreshold;
- u32 TransmitConfig;
- u32 ReceiveConfig;
- u32 IntrMask;
-
- struct chnl_access_setting ChannelAccessSetting;
-};
-
-#define MANAGE_PRIORITY 0
-#define BK_PRIORITY 1
-#define BE_PRIORITY 2
-#define VI_PRIORITY 3
-#define VO_PRIORITY 4
-#define HI_PRIORITY 5
-#define BEACON_PRIORITY 6
-
-#define LOW_PRIORITY VI_PRIORITY
-#define NORM_PRIORITY VO_PRIORITY
-/* AC2Queue mapping. */
-#define AC2Q(_ac) (((_ac) == WME_AC_VO) ? VO_PRIORITY : \
- ((_ac) == WME_AC_VI) ? VI_PRIORITY : \
- ((_ac) == WME_AC_BK) ? BK_PRIORITY : \
- BE_PRIORITY)
-
-short rtl8180_tx(struct net_device *dev, u8 *skbuf, int len, int priority,
- bool morefrag, short fragdesc, int rate);
-
-u8 read_nic_byte(struct net_device *dev, int x);
-u32 read_nic_dword(struct net_device *dev, int x);
-u16 read_nic_word(struct net_device *dev, int x);
-void write_nic_byte(struct net_device *dev, int x, u8 y);
-void write_nic_word(struct net_device *dev, int x, u16 y);
-void write_nic_dword(struct net_device *dev, int x, u32 y);
-void force_pci_posting(struct net_device *dev);
-
-void rtl8180_rtx_disable(struct net_device *);
-void rtl8180_set_anaparam(struct net_device *dev, u32 a);
-void rtl8185_set_anaparam2(struct net_device *dev, u32 a);
-void rtl8180_set_hw_wep(struct net_device *dev);
-void rtl8180_no_hw_wep(struct net_device *dev);
-void rtl8180_update_msr(struct net_device *dev);
-void rtl8180_beacon_tx_disable(struct net_device *dev);
-void rtl8180_beacon_rx_disable(struct net_device *dev);
-int rtl8180_down(struct net_device *dev);
-int rtl8180_up(struct net_device *dev);
-void rtl8180_commit(struct net_device *dev);
-void rtl8180_set_chan(struct net_device *dev, short ch);
-void write_phy(struct net_device *dev, u8 adr, u8 data);
-void write_phy_cck(struct net_device *dev, u8 adr, u32 data);
-void write_phy_ofdm(struct net_device *dev, u8 adr, u32 data);
-void rtl8185_tx_antenna(struct net_device *dev, u8 ant);
-void rtl8185_rf_pins_enable(struct net_device *dev);
-void IPSEnter(struct net_device *dev);
-void IPSLeave(struct net_device *dev);
-int get_curr_tx_free_desc(struct net_device *dev, int priority);
-void UpdateInitialGain(struct net_device *dev);
-bool SetAntennaConfig87SE(struct net_device *dev, u8 DefaultAnt,
- bool bAntDiversity);
-
-void rtl8185b_adapter_start(struct net_device *dev);
-void rtl8185b_rx_enable(struct net_device *dev);
-void rtl8185b_tx_enable(struct net_device *dev);
-void rtl8180_reset(struct net_device *dev);
-void rtl8185b_irq_enable(struct net_device *dev);
-void fix_rx_fifo(struct net_device *dev);
-void fix_tx_fifo(struct net_device *dev);
-void rtl8225z2_SetTXPowerLevel(struct net_device *dev, short ch);
-void rtl8180_rate_adapter(struct work_struct *work);
-bool MgntActSet_RF_State(struct net_device *dev, enum rt_rf_power_state StateToSet,
- u32 ChangeSource);
-
-#endif
-
-/* fun with the built-in ieee80211 stack... */
-extern int ieee80211_crypto_init(void);
-extern void ieee80211_crypto_deinit(void);
-extern int ieee80211_crypto_tkip_init(void);
-extern void ieee80211_crypto_tkip_exit(void);
-extern int ieee80211_crypto_ccmp_init(void);
-extern void ieee80211_crypto_ccmp_exit(void);
-extern int ieee80211_crypto_wep_init(void);
-extern void ieee80211_crypto_wep_exit(void);
diff --git a/drivers/staging/rtl8187se/r8180_93cx6.h b/drivers/staging/rtl8187se/r8180_93cx6.h
deleted file mode 100644
index b52b5b0610ab..000000000000
--- a/drivers/staging/rtl8187se/r8180_93cx6.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- This is part of rtl8180 OpenSource driver
- Copyright (C) Andrea Merello 2004-2005 <andrea.merello@gmail.com>
- Released under the terms of GPL (General Public Licence)
-
- Parts of this driver are based on the GPL part of the official realtek driver
- Parts of this driver are based on the rtl8180 driver skeleton from Patric Schenke & Andres Salomon
- Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver
-
- We want to tanks the Authors of such projects and the Ndiswrapper project Authors.
-*/
-
-/*This files contains card eeprom (93c46 or 93c56) programming routines*/
-/*memory is addressed by WORDS*/
-
-#include "r8180.h"
-#include "r8180_hw.h"
-
-#define EPROM_DELAY 10
-
-#define EPROM_ANAPARAM_ADDRLWORD 0xd
-#define EPROM_ANAPARAM_ADDRHWORD 0xe
-
-#define RFCHIPID 0x6
-#define RFCHIPID_INTERSIL 1
-#define RFCHIPID_RFMD 2
-#define RFCHIPID_PHILIPS 3
-#define RFCHIPID_MAXIM 4
-#define RFCHIPID_GCT 5
-#define RFCHIPID_RTL8225 9
-#define RF_ZEBRA2 11
-#define EPROM_TXPW_BASE 0x05
-#define RF_ZEBRA4 12
-#define RFCHIPID_RTL8255 0xa
-#define RF_PARAM 0x19
-#define RF_PARAM_DIGPHY_SHIFT 0
-#define RF_PARAM_ANTBDEFAULT_SHIFT 1
-#define RF_PARAM_CARRIERSENSE_SHIFT 2
-#define RF_PARAM_CARRIERSENSE_MASK (3<<2)
-#define ENERGY_TRESHOLD 0x17
-#define EPROM_VERSION 0x1E
-#define MAC_ADR 0x7
-
-#define CIS 0x18
-
-#define EPROM_TXPW_OFDM_CH1_2 0x20
-
-#define EPROM_TXPW_CH1_2 0x30
-
-#define RTL818X_EEPROM_CMD_READ (1 << 0)
-#define RTL818X_EEPROM_CMD_WRITE (1 << 1)
-#define RTL818X_EEPROM_CMD_CK (1 << 2)
-#define RTL818X_EEPROM_CMD_CS (1 << 3)
-
diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c
deleted file mode 100644
index a6022d4e7573..000000000000
--- a/drivers/staging/rtl8187se/r8180_core.c
+++ /dev/null
@@ -1,3775 +0,0 @@
-/*
- * This is part of rtl818x pci OpenSource driver - v 0.1
- * Copyright (C) Andrea Merello 2004-2005 <andrea.merello@gmail.com>
- * Released under the terms of GPL (General Public License)
- *
- * Parts of this driver are based on the GPL part of the official
- * Realtek driver.
- *
- * Parts of this driver are based on the rtl8180 driver skeleton
- * from Patric Schenke & Andres Salomon.
- *
- * Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver.
- *
- * Parts of BB/RF code are derived from David Young rtl8180 netbsd driver.
- *
- * RSSI calc function from 'The Deuce'
- *
- * Some ideas borrowed from the 8139too.c driver included in linux kernel.
- *
- * We (I?) want to thanks the Authors of those projecs and also the
- * Ndiswrapper's project Authors.
- *
- * A big big thanks goes also to Realtek corp. for their help in my attempt to
- * add RTL8185 and RTL8225 support, and to David Young also.
- *
- * Power management interface routines.
- * Written by Mariusz Matuszek.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#undef RX_DONT_PASS_UL
-#undef DUMMY_RX
-
-#include <linux/slab.h>
-#include <linux/syscalls.h>
-#include <linux/eeprom_93cx6.h>
-#include <linux/interrupt.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-
-#include "r8180_hw.h"
-#include "r8180.h"
-#include "r8180_rtl8225.h" /* RTL8225 Radio frontend */
-#include "r8180_93cx6.h" /* Card EEPROM */
-#include "r8180_wx.h"
-#include "r8180_dm.h"
-
-#include "ieee80211/dot11d.h"
-
-static struct pci_device_id rtl8180_pci_id_tbl[] = {
- {
- .vendor = PCI_VENDOR_ID_REALTEK,
- .device = 0x8199,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = 0,
- },
- {
- .vendor = 0,
- .device = 0,
- .subvendor = 0,
- .subdevice = 0,
- .driver_data = 0,
- }
-};
-
-static char ifname[IFNAMSIZ] = "wlan%d";
-static int hwwep;
-
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(pci, rtl8180_pci_id_tbl);
-MODULE_AUTHOR("Andrea Merello <andrea.merello@gmail.com>");
-MODULE_DESCRIPTION("Linux driver for Realtek RTL8187SE WiFi cards");
-
-module_param_string(ifname, ifname, sizeof(ifname), S_IRUGO|S_IWUSR);
-module_param(hwwep, int, S_IRUGO|S_IWUSR);
-
-MODULE_PARM_DESC(hwwep, " Try to use hardware WEP support. Still broken and not available on all cards");
-
-static int rtl8180_pci_probe(struct pci_dev *pdev,
- const struct pci_device_id *id);
-
-static void rtl8180_pci_remove(struct pci_dev *pdev);
-
-static void rtl8180_shutdown(struct pci_dev *pdev)
-{
- struct net_device *dev = pci_get_drvdata(pdev);
- if (dev->netdev_ops->ndo_stop)
- dev->netdev_ops->ndo_stop(dev);
- pci_disable_device(pdev);
-}
-
-static int rtl8180_suspend(struct pci_dev *pdev, pm_message_t state)
-{
- struct net_device *dev = pci_get_drvdata(pdev);
-
- if (!netif_running(dev))
- goto out_pci_suspend;
-
- if (dev->netdev_ops->ndo_stop)
- dev->netdev_ops->ndo_stop(dev);
-
- netif_device_detach(dev);
-
-out_pci_suspend:
- pci_save_state(pdev);
- pci_disable_device(pdev);
- pci_set_power_state(pdev, pci_choose_state(pdev, state));
- return 0;
-}
-
-static int rtl8180_resume(struct pci_dev *pdev)
-{
- struct net_device *dev = pci_get_drvdata(pdev);
- int err;
- u32 val;
-
- pci_set_power_state(pdev, PCI_D0);
-
- err = pci_enable_device(pdev);
- if (err) {
- dev_err(&pdev->dev, "pci_enable_device failed on resume\n");
-
- return err;
- }
-
- pci_restore_state(pdev);
-
- /*
- * Suspend/Resume resets the PCI configuration space, so we have to
- * re-disable the RETRY_TIMEOUT register (0x41) to keep PCI Tx retries
- * from interfering with C3 CPU state. pci_restore_state won't help
- * here since it only restores the first 64 bytes pci config header.
- */
- pci_read_config_dword(pdev, 0x40, &val);
- if ((val & 0x0000ff00) != 0)
- pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
-
- if (!netif_running(dev))
- goto out;
-
- if (dev->netdev_ops->ndo_open)
- dev->netdev_ops->ndo_open(dev);
-
- netif_device_attach(dev);
-out:
- return 0;
-}
-
-static struct pci_driver rtl8180_pci_driver = {
- .name = RTL8180_MODULE_NAME,
- .id_table = rtl8180_pci_id_tbl,
- .probe = rtl8180_pci_probe,
- .remove = rtl8180_pci_remove,
- .suspend = rtl8180_suspend,
- .resume = rtl8180_resume,
- .shutdown = rtl8180_shutdown,
-};
-
-u8 read_nic_byte(struct net_device *dev, int x)
-{
- return 0xff&readb((u8 __iomem *)dev->mem_start + x);
-}
-
-u32 read_nic_dword(struct net_device *dev, int x)
-{
- return readl((u8 __iomem *)dev->mem_start + x);
-}
-
-u16 read_nic_word(struct net_device *dev, int x)
-{
- return readw((u8 __iomem *)dev->mem_start + x);
-}
-
-void write_nic_byte(struct net_device *dev, int x, u8 y)
-{
- writeb(y, (u8 __iomem *)dev->mem_start + x);
- udelay(20);
-}
-
-void write_nic_dword(struct net_device *dev, int x, u32 y)
-{
- writel(y, (u8 __iomem *)dev->mem_start + x);
- udelay(20);
-}
-
-void write_nic_word(struct net_device *dev, int x, u16 y)
-{
- writew(y, (u8 __iomem *)dev->mem_start + x);
- udelay(20);
-}
-
-inline void force_pci_posting(struct net_device *dev)
-{
- read_nic_byte(dev, EPROM_CMD);
- mb();
-}
-
-static irqreturn_t rtl8180_interrupt(int irq, void *netdev);
-void set_nic_rxring(struct net_device *dev);
-void set_nic_txring(struct net_device *dev);
-static struct net_device_stats *rtl8180_stats(struct net_device *dev);
-void rtl8180_commit(struct net_device *dev);
-void rtl8180_start_tx_beacon(struct net_device *dev);
-
-static struct proc_dir_entry *rtl8180_proc;
-
-static int proc_get_registers(struct seq_file *m, void *v)
-{
- struct net_device *dev = m->private;
- int i, n, max = 0xff;
-
- /* This dump the current register page */
- for (n = 0; n <= max;) {
- seq_printf(m, "\nD: %2x > ", n);
-
- for (i = 0; i < 16 && n <= max; i++, n++)
- seq_printf(m, "%2x ", read_nic_byte(dev, n));
- }
- seq_putc(m, '\n');
- return 0;
-}
-
-int get_curr_tx_free_desc(struct net_device *dev, int priority);
-
-static int proc_get_stats_hw(struct seq_file *m, void *v)
-{
- return 0;
-}
-
-static int proc_get_stats_rx(struct seq_file *m, void *v)
-{
- struct net_device *dev = m->private;
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
- seq_printf(m,
- "RX OK: %lu\n"
- "RX Retry: %lu\n"
- "RX CRC Error(0-500): %lu\n"
- "RX CRC Error(500-1000): %lu\n"
- "RX CRC Error(>1000): %lu\n"
- "RX ICV Error: %lu\n",
- priv->stats.rxint,
- priv->stats.rxerr,
- priv->stats.rxcrcerrmin,
- priv->stats.rxcrcerrmid,
- priv->stats.rxcrcerrmax,
- priv->stats.rxicverr
- );
-
- return 0;
-}
-
-static int proc_get_stats_tx(struct seq_file *m, void *v)
-{
- struct net_device *dev = m->private;
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- unsigned long totalOK;
-
- totalOK = priv->stats.txnpokint + priv->stats.txhpokint +
- priv->stats.txlpokint;
-
- seq_printf(m,
- "TX OK: %lu\n"
- "TX Error: %lu\n"
- "TX Retry: %lu\n"
- "TX beacon OK: %lu\n"
- "TX beacon error: %lu\n",
- totalOK,
- priv->stats.txnperr+priv->stats.txhperr+priv->stats.txlperr,
- priv->stats.txretry,
- priv->stats.txbeacon,
- priv->stats.txbeaconerr
- );
-
- return 0;
-}
-
-static void rtl8180_proc_module_init(void)
-{
- DMESG("Initializing proc filesystem");
- rtl8180_proc = proc_mkdir(RTL8180_MODULE_NAME, init_net.proc_net);
-}
-
-static void rtl8180_proc_module_remove(void)
-{
- remove_proc_entry(RTL8180_MODULE_NAME, init_net.proc_net);
-}
-
-static void rtl8180_proc_remove_one(struct net_device *dev)
-{
- remove_proc_subtree(dev->name, rtl8180_proc);
-}
-
-/*
- * seq_file wrappers for procfile show routines.
- */
-static int rtl8180_proc_open(struct inode *inode, struct file *file)
-{
- struct net_device *dev = proc_get_parent_data(inode);
- int (*show)(struct seq_file *, void *) = PDE_DATA(inode);
-
- return single_open(file, show, dev);
-}
-
-static const struct file_operations rtl8180_proc_fops = {
- .open = rtl8180_proc_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-/*
- * Table of proc files we need to create.
- */
-struct rtl8180_proc_file {
- char name[12];
- int (*show)(struct seq_file *, void *);
-};
-
-static const struct rtl8180_proc_file rtl8180_proc_files[] = {
- { "stats-hw", &proc_get_stats_hw },
- { "stats-rx", &proc_get_stats_rx },
- { "stats-tx", &proc_get_stats_tx },
- { "registers", &proc_get_registers },
- { "" }
-};
-
-static void rtl8180_proc_init_one(struct net_device *dev)
-{
- const struct rtl8180_proc_file *f;
- struct proc_dir_entry *dir;
-
- dir = proc_mkdir_data(dev->name, 0, rtl8180_proc, dev);
- if (!dir) {
- DMESGE("Unable to initialize /proc/net/r8180/%s\n", dev->name);
- return;
- }
-
- for (f = rtl8180_proc_files; f->name[0]; f++) {
- if (!proc_create_data(f->name, S_IFREG | S_IRUGO, dir,
- &rtl8180_proc_fops, f->show)) {
- DMESGE("Unable to initialize /proc/net/r8180/%s/%s\n",
- dev->name, f->name);
- return;
- }
- }
-}
-
-/*
- * FIXME: check if we can use some standard already-existent
- * data type+functions in kernel.
- */
-
-static short buffer_add(struct buffer **buffer, u32 *buf, dma_addr_t dma,
- struct buffer **bufferhead)
-{
- struct buffer *tmp;
-
- if (!*buffer) {
-
- *buffer = kmalloc(sizeof(struct buffer), GFP_KERNEL);
-
- if (*buffer == NULL) {
- DMESGE("Failed to kmalloc head of TX/RX struct");
- return -1;
- }
- (*buffer)->next = *buffer;
- (*buffer)->buf = buf;
- (*buffer)->dma = dma;
- if (bufferhead != NULL)
- (*bufferhead) = (*buffer);
- return 0;
- }
- tmp = *buffer;
-
- while (tmp->next != (*buffer))
- tmp = tmp->next;
- tmp->next = kmalloc(sizeof(struct buffer), GFP_KERNEL);
- if (tmp->next == NULL) {
- DMESGE("Failed to kmalloc TX/RX struct");
- return -1;
- }
- tmp->next->buf = buf;
- tmp->next->dma = dma;
- tmp->next->next = *buffer;
-
- return 0;
-}
-
-static void buffer_free(struct net_device *dev, struct buffer **buffer, int len,
- short consistent)
-{
-
- struct buffer *tmp, *next;
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- struct pci_dev *pdev = priv->pdev;
-
- if (!*buffer)
- return;
-
- tmp = *buffer;
-
- do {
- next = tmp->next;
- if (consistent) {
- pci_free_consistent(pdev, len,
- tmp->buf, tmp->dma);
- } else {
- pci_unmap_single(pdev, tmp->dma,
- len, PCI_DMA_FROMDEVICE);
- kfree(tmp->buf);
- }
- kfree(tmp);
- tmp = next;
- } while (next != *buffer);
-
- *buffer = NULL;
-}
-
-int get_curr_tx_free_desc(struct net_device *dev, int priority)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- u32 *tail;
- u32 *head;
- int ret;
-
- switch (priority) {
- case MANAGE_PRIORITY:
- head = priv->txmapringhead;
- tail = priv->txmapringtail;
- break;
- case BK_PRIORITY:
- head = priv->txbkpringhead;
- tail = priv->txbkpringtail;
- break;
- case BE_PRIORITY:
- head = priv->txbepringhead;
- tail = priv->txbepringtail;
- break;
- case VI_PRIORITY:
- head = priv->txvipringhead;
- tail = priv->txvipringtail;
- break;
- case VO_PRIORITY:
- head = priv->txvopringhead;
- tail = priv->txvopringtail;
- break;
- case HI_PRIORITY:
- head = priv->txhpringhead;
- tail = priv->txhpringtail;
- break;
- default:
- return -1;
- }
-
- if (head <= tail)
- ret = priv->txringcount - (tail - head)/8;
- else
- ret = (head - tail)/8;
-
- if (ret > priv->txringcount)
- DMESG("BUG");
-
- return ret;
-}
-
-static short check_nic_enought_desc(struct net_device *dev, int priority)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- struct ieee80211_device *ieee = netdev_priv(dev);
- int requiredbyte;
- int required;
-
- requiredbyte = priv->ieee80211->fts +
- sizeof(struct ieee80211_header_data);
-
- if (ieee->current_network.QoS_Enable)
- requiredbyte += 2;
-
- required = requiredbyte / (priv->txbuffsize-4);
-
- if (requiredbyte % priv->txbuffsize)
- required++;
-
- /* for now we keep two free descriptor as a safety boundary
- * between the tail and the head
- */
-
- return required + 2 < get_curr_tx_free_desc(dev, priority);
-}
-
-void fix_tx_fifo(struct net_device *dev)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- u32 *tmp;
- int i;
-
- for (tmp = priv->txmapring, i = 0;
- i < priv->txringcount;
- tmp += 8, i++) {
- *tmp = *tmp & ~(1<<31);
- }
-
- for (tmp = priv->txbkpring, i = 0;
- i < priv->txringcount;
- tmp += 8, i++) {
- *tmp = *tmp & ~(1<<31);
- }
-
- for (tmp = priv->txbepring, i = 0;
- i < priv->txringcount;
- tmp += 8, i++) {
- *tmp = *tmp & ~(1<<31);
- }
- for (tmp = priv->txvipring, i = 0;
- i < priv->txringcount;
- tmp += 8, i++) {
- *tmp = *tmp & ~(1<<31);
- }
-
- for (tmp = priv->txvopring, i = 0;
- i < priv->txringcount;
- tmp += 8, i++) {
- *tmp = *tmp & ~(1<<31);
- }
-
- for (tmp = priv->txhpring, i = 0;
- i < priv->txringcount;
- tmp += 8, i++) {
- *tmp = *tmp & ~(1<<31);
- }
-
- for (tmp = priv->txbeaconring, i = 0;
- i < priv->txbeaconcount;
- tmp += 8, i++) {
- *tmp = *tmp & ~(1<<31);
- }
-
- priv->txmapringtail = priv->txmapring;
- priv->txmapringhead = priv->txmapring;
- priv->txmapbufstail = priv->txmapbufs;
-
- priv->txbkpringtail = priv->txbkpring;
- priv->txbkpringhead = priv->txbkpring;
- priv->txbkpbufstail = priv->txbkpbufs;
-
- priv->txbepringtail = priv->txbepring;
- priv->txbepringhead = priv->txbepring;
- priv->txbepbufstail = priv->txbepbufs;
-
- priv->txvipringtail = priv->txvipring;
- priv->txvipringhead = priv->txvipring;
- priv->txvipbufstail = priv->txvipbufs;
-
- priv->txvopringtail = priv->txvopring;
- priv->txvopringhead = priv->txvopring;
- priv->txvopbufstail = priv->txvopbufs;
-
- priv->txhpringtail = priv->txhpring;
- priv->txhpringhead = priv->txhpring;
- priv->txhpbufstail = priv->txhpbufs;
-
- priv->txbeaconringtail = priv->txbeaconring;
- priv->txbeaconbufstail = priv->txbeaconbufs;
- set_nic_txring(dev);
-
- ieee80211_reset_queue(priv->ieee80211);
- priv->ack_tx_to_ieee = 0;
-}
-
-void fix_rx_fifo(struct net_device *dev)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- u32 *tmp;
- struct buffer *rxbuf;
- u8 rx_desc_size;
-
- rx_desc_size = 8; /* 4*8 = 32 bytes */
-
- for (tmp = priv->rxring, rxbuf = priv->rxbufferhead;
- (tmp < (priv->rxring)+(priv->rxringcount)*rx_desc_size);
- tmp += rx_desc_size, rxbuf = rxbuf->next) {
- *(tmp+2) = rxbuf->dma;
- *tmp = *tmp & ~0xfff;
- *tmp = *tmp | priv->rxbuffersize;
- *tmp |= (1<<31);
- }
-
- priv->rxringtail = priv->rxring;
- priv->rxbuffer = priv->rxbufferhead;
- priv->rx_skb_complete = 1;
- set_nic_rxring(dev);
-}
-
-static void rtl8180_irq_disable(struct net_device *dev)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
- write_nic_dword(dev, IMR, 0);
- force_pci_posting(dev);
- priv->irq_enabled = 0;
-}
-
-void rtl8180_set_mode(struct net_device *dev, int mode)
-{
- u8 ecmd;
-
- ecmd = read_nic_byte(dev, EPROM_CMD);
- ecmd = ecmd & ~EPROM_CMD_OPERATING_MODE_MASK;
- ecmd = ecmd | (mode<<EPROM_CMD_OPERATING_MODE_SHIFT);
- ecmd = ecmd & ~(1<<EPROM_CS_SHIFT);
- ecmd = ecmd & ~(1<<EPROM_CK_SHIFT);
- write_nic_byte(dev, EPROM_CMD, ecmd);
-}
-
-void rtl8180_beacon_tx_enable(struct net_device *dev);
-
-void rtl8180_update_msr(struct net_device *dev)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- u8 msr;
- u32 rxconf;
-
- msr = read_nic_byte(dev, MSR);
- msr &= ~MSR_LINK_MASK;
-
- rxconf = read_nic_dword(dev, RX_CONF);
-
- if (priv->ieee80211->state == IEEE80211_LINKED) {
- if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
- msr |= (MSR_LINK_ADHOC<<MSR_LINK_SHIFT);
- else if (priv->ieee80211->iw_mode == IW_MODE_MASTER)
- msr |= (MSR_LINK_MASTER<<MSR_LINK_SHIFT);
- else if (priv->ieee80211->iw_mode == IW_MODE_INFRA)
- msr |= (MSR_LINK_MANAGED<<MSR_LINK_SHIFT);
- else
- msr |= (MSR_LINK_NONE<<MSR_LINK_SHIFT);
- rxconf |= (1<<RX_CHECK_BSSID_SHIFT);
-
- } else {
- msr |= (MSR_LINK_NONE<<MSR_LINK_SHIFT);
- rxconf &= ~(1<<RX_CHECK_BSSID_SHIFT);
- }
-
- write_nic_byte(dev, MSR, msr);
- write_nic_dword(dev, RX_CONF, rxconf);
-}
-
-void rtl8180_set_chan(struct net_device *dev, short ch)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
- if ((ch > 14) || (ch < 1)) {
- netdev_err(dev, "In %s: Invalid channel %d\n", __func__, ch);
- return;
- }
-
- priv->chan = ch;
- priv->rf_set_chan(dev, priv->chan);
-}
-
-void set_nic_txring(struct net_device *dev)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
- write_nic_dword(dev, TX_MANAGEPRIORITY_RING_ADDR, priv->txmapringdma);
- write_nic_dword(dev, TX_BKPRIORITY_RING_ADDR, priv->txbkpringdma);
- write_nic_dword(dev, TX_BEPRIORITY_RING_ADDR, priv->txbepringdma);
- write_nic_dword(dev, TX_VIPRIORITY_RING_ADDR, priv->txvipringdma);
- write_nic_dword(dev, TX_VOPRIORITY_RING_ADDR, priv->txvopringdma);
- write_nic_dword(dev, TX_HIGHPRIORITY_RING_ADDR, priv->txhpringdma);
- write_nic_dword(dev, TX_BEACON_RING_ADDR, priv->txbeaconringdma);
-}
-
-void rtl8180_beacon_tx_enable(struct net_device *dev)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
- rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
- priv->dma_poll_stop_mask &= ~(TPPOLLSTOP_BQ);
- write_nic_byte(dev, TPPollStop, priv->dma_poll_mask);
- rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
-}
-
-void rtl8180_beacon_tx_disable(struct net_device *dev)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
- rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
- priv->dma_poll_stop_mask |= TPPOLLSTOP_BQ;
- write_nic_byte(dev, TPPollStop, priv->dma_poll_stop_mask);
- rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
-
-}
-
-void rtl8180_rtx_disable(struct net_device *dev)
-{
- u8 cmd;
- struct r8180_priv *priv = ieee80211_priv(dev);
-
- cmd = read_nic_byte(dev, CMD);
- write_nic_byte(dev, CMD, cmd &
- ~((1<<CMD_RX_ENABLE_SHIFT)|(1<<CMD_TX_ENABLE_SHIFT)));
- force_pci_posting(dev);
- mdelay(10);
-
- if (!priv->rx_skb_complete)
- dev_kfree_skb_any(priv->rx_skb);
-}
-
-static short alloc_tx_desc_ring(struct net_device *dev, int bufsize, int count,
- int addr)
-{
- int i;
- u32 *desc;
- u32 *tmp;
- dma_addr_t dma_desc, dma_tmp;
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- struct pci_dev *pdev = priv->pdev;
- void *buf;
-
- if ((bufsize & 0xfff) != bufsize) {
- DMESGE("TX buffer allocation too large");
- return 0;
- }
- desc = (u32 *)pci_alloc_consistent(pdev,
- sizeof(u32)*8*count+256, &dma_desc);
- if (desc == NULL)
- return -1;
-
- if (dma_desc & 0xff)
- /*
- * descriptor's buffer must be 256 byte aligned
- * we shouldn't be here, since we set DMA mask !
- */
- WARN(1, "DMA buffer is not aligned\n");
-
- tmp = desc;
-
- for (i = 0; i < count; i++) {
- buf = (void *)pci_alloc_consistent(pdev, bufsize, &dma_tmp);
- if (buf == NULL)
- return -ENOMEM;
-
- switch (addr) {
- case TX_MANAGEPRIORITY_RING_ADDR:
- if (-1 == buffer_add(&priv->txmapbufs,
- buf, dma_tmp, NULL)) {
- DMESGE("Unable to allocate mem for buffer NP");
- return -ENOMEM;
- }
- break;
- case TX_BKPRIORITY_RING_ADDR:
- if (-1 == buffer_add(&priv->txbkpbufs,
- buf, dma_tmp, NULL)) {
- DMESGE("Unable to allocate mem for buffer LP");
- return -ENOMEM;
- }
- break;
- case TX_BEPRIORITY_RING_ADDR:
- if (-1 == buffer_add(&priv->txbepbufs,
- buf, dma_tmp, NULL)) {
- DMESGE("Unable to allocate mem for buffer NP");
- return -ENOMEM;
- }
- break;
- case TX_VIPRIORITY_RING_ADDR:
- if (-1 == buffer_add(&priv->txvipbufs,
- buf, dma_tmp, NULL)) {
- DMESGE("Unable to allocate mem for buffer LP");
- return -ENOMEM;
- }
- break;
- case TX_VOPRIORITY_RING_ADDR:
- if (-1 == buffer_add(&priv->txvopbufs,
- buf, dma_tmp, NULL)) {
- DMESGE("Unable to allocate mem for buffer NP");
- return -ENOMEM;
- }
- break;
- case TX_HIGHPRIORITY_RING_ADDR:
- if (-1 == buffer_add(&priv->txhpbufs,
- buf, dma_tmp, NULL)) {
- DMESGE("Unable to allocate mem for buffer HP");
- return -ENOMEM;
- }
- break;
- case TX_BEACON_RING_ADDR:
- if (-1 == buffer_add(&priv->txbeaconbufs,
- buf, dma_tmp, NULL)) {
- DMESGE("Unable to allocate mem for buffer BP");
- return -ENOMEM;
- }
- break;
- }
- *tmp = *tmp & ~(1<<31); /* descriptor empty, owned by the drv */
- *(tmp+2) = (u32)dma_tmp;
- *(tmp+3) = bufsize;
-
- if (i+1 < count)
- *(tmp+4) = (u32)dma_desc+((i+1)*8*4);
- else
- *(tmp+4) = (u32)dma_desc;
-
- tmp = tmp+8;
- }
-
- switch (addr) {
- case TX_MANAGEPRIORITY_RING_ADDR:
- priv->txmapringdma = dma_desc;
- priv->txmapring = desc;
- break;
- case TX_BKPRIORITY_RING_ADDR:
- priv->txbkpringdma = dma_desc;
- priv->txbkpring = desc;
- break;
- case TX_BEPRIORITY_RING_ADDR:
- priv->txbepringdma = dma_desc;
- priv->txbepring = desc;
- break;
- case TX_VIPRIORITY_RING_ADDR:
- priv->txvipringdma = dma_desc;
- priv->txvipring = desc;
- break;
- case TX_VOPRIORITY_RING_ADDR:
- priv->txvopringdma = dma_desc;
- priv->txvopring = desc;
- break;
- case TX_HIGHPRIORITY_RING_ADDR:
- priv->txhpringdma = dma_desc;
- priv->txhpring = desc;
- break;
- case TX_BEACON_RING_ADDR:
- priv->txbeaconringdma = dma_desc;
- priv->txbeaconring = desc;
- break;
-
- }
-
- return 0;
-}
-
-static void free_tx_desc_rings(struct net_device *dev)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- struct pci_dev *pdev = priv->pdev;
- int count = priv->txringcount;
-
- pci_free_consistent(pdev, sizeof(u32)*8*count+256,
- priv->txmapring, priv->txmapringdma);
- buffer_free(dev, &(priv->txmapbufs), priv->txbuffsize, 1);
-
- pci_free_consistent(pdev, sizeof(u32)*8*count+256,
- priv->txbkpring, priv->txbkpringdma);
- buffer_free(dev, &(priv->txbkpbufs), priv->txbuffsize, 1);
-
- pci_free_consistent(pdev, sizeof(u32)*8*count+256,
- priv->txbepring, priv->txbepringdma);
- buffer_free(dev, &(priv->txbepbufs), priv->txbuffsize, 1);
-
- pci_free_consistent(pdev, sizeof(u32)*8*count+256,
- priv->txvipring, priv->txvipringdma);
- buffer_free(dev, &(priv->txvipbufs), priv->txbuffsize, 1);
-
- pci_free_consistent(pdev, sizeof(u32)*8*count+256,
- priv->txvopring, priv->txvopringdma);
- buffer_free(dev, &(priv->txvopbufs), priv->txbuffsize, 1);
-
- pci_free_consistent(pdev, sizeof(u32)*8*count+256,
- priv->txhpring, priv->txhpringdma);
- buffer_free(dev, &(priv->txhpbufs), priv->txbuffsize, 1);
-
- count = priv->txbeaconcount;
- pci_free_consistent(pdev, sizeof(u32)*8*count+256,
- priv->txbeaconring, priv->txbeaconringdma);
- buffer_free(dev, &(priv->txbeaconbufs), priv->txbuffsize, 1);
-}
-
-static void free_rx_desc_ring(struct net_device *dev)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- struct pci_dev *pdev = priv->pdev;
- int count = priv->rxringcount;
-
- pci_free_consistent(pdev, sizeof(u32)*8*count+256,
- priv->rxring, priv->rxringdma);
-
- buffer_free(dev, &(priv->rxbuffer), priv->rxbuffersize, 0);
-}
-
-static short alloc_rx_desc_ring(struct net_device *dev, u16 bufsize, int count)
-{
- int i;
- u32 *desc;
- u32 *tmp;
- dma_addr_t dma_desc, dma_tmp;
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- struct pci_dev *pdev = priv->pdev;
- void *buf;
- u8 rx_desc_size;
-
- rx_desc_size = 8; /* 4*8 = 32 bytes */
-
- if ((bufsize & 0xfff) != bufsize) {
- DMESGE("RX buffer allocation too large");
- return -1;
- }
-
- desc = (u32 *)pci_alloc_consistent(pdev,
- sizeof(u32) * rx_desc_size * count + 256, &dma_desc);
-
- if (dma_desc & 0xff)
- /*
- * descriptor's buffer must be 256 byte aligned
- * should never happen since we specify the DMA mask
- */
- WARN(1, "DMA buffer is not aligned\n");
-
- priv->rxring = desc;
- priv->rxringdma = dma_desc;
- tmp = desc;
-
- for (i = 0; i < count; i++) {
- buf = kmalloc(bufsize * sizeof(u8), GFP_ATOMIC);
- if (buf == NULL) {
- DMESGE("Failed to kmalloc RX buffer");
- return -1;
- }
-
- dma_tmp = pci_map_single(pdev, buf, bufsize * sizeof(u8),
- PCI_DMA_FROMDEVICE);
- if (pci_dma_mapping_error(pdev, dma_tmp))
- return -1;
- if (-1 == buffer_add(&(priv->rxbuffer), buf, dma_tmp,
- &(priv->rxbufferhead))) {
- DMESGE("Unable to allocate mem RX buf");
- return -1;
- }
- *tmp = 0; /* zero pads the header of the descriptor */
- *tmp = *tmp | (bufsize&0xfff);
- *(tmp+2) = (u32)dma_tmp;
- *tmp = *tmp | (1<<31); /* descriptor void, owned by the NIC */
-
- tmp = tmp+rx_desc_size;
- }
-
- /* this is the last descriptor */
- *(tmp - rx_desc_size) = *(tmp - rx_desc_size) | (1 << 30);
-
- return 0;
-}
-
-
-void set_nic_rxring(struct net_device *dev)
-{
- u8 pgreg;
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
- pgreg = read_nic_byte(dev, PGSELECT);
- write_nic_byte(dev, PGSELECT, pgreg & ~(1<<PGSELECT_PG_SHIFT));
-
- write_nic_dword(dev, RXRING_ADDR, priv->rxringdma);
-}
-
-void rtl8180_reset(struct net_device *dev)
-{
- u8 cr;
-
- rtl8180_irq_disable(dev);
-
- cr = read_nic_byte(dev, CMD);
- cr = cr & 2;
- cr = cr | (1<<CMD_RST_SHIFT);
- write_nic_byte(dev, CMD, cr);
-
- force_pci_posting(dev);
-
- mdelay(200);
-
- if (read_nic_byte(dev, CMD) & (1<<CMD_RST_SHIFT))
- DMESGW("Card reset timeout!");
- else
- DMESG("Card successfully reset");
-
- rtl8180_set_mode(dev, EPROM_CMD_LOAD);
- force_pci_posting(dev);
- mdelay(200);
-}
-
-inline u16 ieeerate2rtlrate(int rate)
-{
- switch (rate) {
- case 10:
- return 0;
- case 20:
- return 1;
- case 55:
- return 2;
- case 110:
- return 3;
- case 60:
- return 4;
- case 90:
- return 5;
- case 120:
- return 6;
- case 180:
- return 7;
- case 240:
- return 8;
- case 360:
- return 9;
- case 480:
- return 10;
- case 540:
- return 11;
- default:
- return 3;
- }
-}
-
-static u16 rtl_rate[] = {10, 20, 55, 110, 60,
- 90, 120, 180, 240, 360, 480, 540, 720};
-
-inline u16 rtl8180_rate2rate(short rate)
-{
- if (rate > 12)
- return 10;
- return rtl_rate[rate];
-}
-
-inline u8 rtl8180_IsWirelessBMode(u16 rate)
-{
- if (((rate <= 110) && (rate != 60) && (rate != 90)) || (rate == 220))
- return 1;
- else
- return 0;
-}
-
-u16 N_DBPSOfRate(u16 DataRate);
-
-static u16 ComputeTxTime(u16 FrameLength, u16 DataRate, u8 bManagementFrame,
- u8 bShortPreamble)
-{
- u16 FrameTime;
- u16 N_DBPS;
- u16 Ceiling;
-
- if (rtl8180_IsWirelessBMode(DataRate)) {
- if (bManagementFrame || !bShortPreamble || DataRate == 10)
- /* long preamble */
- FrameTime = (u16)(144+48+(FrameLength*8/(DataRate/10)));
- else
- /* short preamble */
- FrameTime = (u16)(72+24+(FrameLength*8/(DataRate/10)));
-
- if ((FrameLength*8 % (DataRate/10)) != 0) /* get the ceilling */
- FrameTime++;
- } else { /* 802.11g DSSS-OFDM PLCP length field calculation. */
- N_DBPS = N_DBPSOfRate(DataRate);
- Ceiling = (16 + 8*FrameLength + 6) / N_DBPS
- + (((16 + 8*FrameLength + 6) % N_DBPS) ? 1 : 0);
- FrameTime = (u16)(16 + 4 + 4*Ceiling + 6);
- }
- return FrameTime;
-}
-
-u16 N_DBPSOfRate(u16 DataRate)
-{
- u16 N_DBPS = 24;
-
- switch (DataRate) {
- case 60:
- N_DBPS = 24;
- break;
- case 90:
- N_DBPS = 36;
- break;
- case 120:
- N_DBPS = 48;
- break;
- case 180:
- N_DBPS = 72;
- break;
- case 240:
- N_DBPS = 96;
- break;
- case 360:
- N_DBPS = 144;
- break;
- case 480:
- N_DBPS = 192;
- break;
- case 540:
- N_DBPS = 216;
- break;
- default:
- break;
- }
-
- return N_DBPS;
-}
-
-/*
- * For Netgear case, they want good-looking signal strength.
- */
-static long NetgearSignalStrengthTranslate(long LastSS, long CurrSS)
-{
- long RetSS;
-
- /* Step 1. Scale mapping. */
- if (CurrSS >= 71 && CurrSS <= 100)
- RetSS = 90 + ((CurrSS - 70) / 3);
- else if (CurrSS >= 41 && CurrSS <= 70)
- RetSS = 78 + ((CurrSS - 40) / 3);
- else if (CurrSS >= 31 && CurrSS <= 40)
- RetSS = 66 + (CurrSS - 30);
- else if (CurrSS >= 21 && CurrSS <= 30)
- RetSS = 54 + (CurrSS - 20);
- else if (CurrSS >= 5 && CurrSS <= 20)
- RetSS = 42 + (((CurrSS - 5) * 2) / 3);
- else if (CurrSS == 4)
- RetSS = 36;
- else if (CurrSS == 3)
- RetSS = 27;
- else if (CurrSS == 2)
- RetSS = 18;
- else if (CurrSS == 1)
- RetSS = 9;
- else
- RetSS = CurrSS;
-
- /* Step 2. Smoothing. */
- if (LastSS > 0)
- RetSS = ((LastSS * 5) + (RetSS) + 5) / 6;
-
- return RetSS;
-}
-
-/*
- * Translate 0-100 signal strength index into dBm.
- */
-static long TranslateToDbm8185(u8 SignalStrengthIndex)
-{
- long SignalPower;
-
- /* Translate to dBm (x=0.5y-95). */
- SignalPower = (long)((SignalStrengthIndex + 1) >> 1);
- SignalPower -= 95;
-
- return SignalPower;
-}
-
-/*
- * Perform signal smoothing for dynamic mechanism.
- * This is different with PerformSignalSmoothing8185 in smoothing formula.
- * No dramatic adjustment is applied because dynamic mechanism need some
- * degree of correctness. Ported from 8187B.
- */
-static void PerformUndecoratedSignalSmoothing8185(struct r8180_priv *priv,
- bool bCckRate)
-{
- long smoothedSS;
- long smoothedRx;
-
- /* Determine the current packet is CCK rate. */
- priv->bCurCCKPkt = bCckRate;
-
- smoothedSS = priv->SignalStrength * 10;
-
- if (priv->UndecoratedSmoothedSS >= 0)
- smoothedSS = ((priv->UndecoratedSmoothedSS * 5) +
- smoothedSS) / 6;
-
- priv->UndecoratedSmoothedSS = smoothedSS;
-
- smoothedRx = ((priv->UndecoratedSmoothedRxPower * 50) +
- (priv->RxPower * 11)) / 60;
-
- priv->UndecoratedSmoothedRxPower = smoothedRx;
-
- if (bCckRate)
- priv->CurCCKRSSI = priv->RSSI;
- else
- priv->CurCCKRSSI = 0;
-}
-
-
-/*
- * This is rough RX isr handling routine
- */
-static void rtl8180_rx(struct net_device *dev)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- struct sk_buff *tmp_skb;
- short first, last;
- u32 len;
- int lastlen;
- unsigned char quality, signal;
- u8 rate;
- u32 *tmp, *tmp2;
- u8 rx_desc_size;
- u8 padding;
- char rxpower = 0;
- u32 RXAGC = 0;
- long RxAGC_dBm = 0;
- u8 LNA = 0, BB = 0;
- u8 LNA_gain[4] = {02, 17, 29, 39};
- u8 Antenna = 0;
- struct ieee80211_hdr_4addr *hdr;
- u16 fc, type;
- u8 bHwError = 0, bCRC = 0, bICV = 0;
- bool bCckRate = false;
- u8 RSSI = 0;
- long SignalStrengthIndex = 0;
- struct ieee80211_rx_stats stats = {
- .signal = 0,
- .noise = -98,
- .rate = 0,
- .freq = IEEE80211_24GHZ_BAND,
- };
-
- stats.nic_type = NIC_8185B;
- rx_desc_size = 8;
-
- if ((*(priv->rxringtail)) & (1<<31)) {
- /* we have got an RX int, but the descriptor. we are pointing
- * is empty.
- */
-
- priv->stats.rxnodata++;
- priv->ieee80211->stats.rx_errors++;
-
- tmp2 = NULL;
- tmp = priv->rxringtail;
- do {
- if (tmp == priv->rxring)
- tmp = priv->rxring + (priv->rxringcount - 1) *
- rx_desc_size;
- else
- tmp -= rx_desc_size;
-
- if (!(*tmp & (1<<31)))
- tmp2 = tmp;
- } while (tmp != priv->rxring);
-
- if (tmp2)
- priv->rxringtail = tmp2;
- }
-
- /* while there are filled descriptors */
- while (!(*(priv->rxringtail) & (1<<31))) {
- if (*(priv->rxringtail) & (1<<26))
- DMESGW("RX buffer overflow");
- if (*(priv->rxringtail) & (1<<12))
- priv->stats.rxicverr++;
-
- if (*(priv->rxringtail) & (1<<27)) {
- priv->stats.rxdmafail++;
- goto drop;
- }
-
- pci_dma_sync_single_for_cpu(priv->pdev,
- priv->rxbuffer->dma,
- priv->rxbuffersize * sizeof(u8),
- PCI_DMA_FROMDEVICE);
-
- first = *(priv->rxringtail) & (1<<29) ? 1 : 0;
- if (first)
- priv->rx_prevlen = 0;
-
- last = *(priv->rxringtail) & (1<<28) ? 1 : 0;
- if (last) {
- lastlen = ((*priv->rxringtail) & 0xfff);
-
- /* if the last descriptor (that should tell us the total
- * packet len) tell us something less than the
- * descriptors len we had until now, then there is some
- * problem..
- * workaround to prevent kernel panic
- */
- if (lastlen < priv->rx_prevlen)
- len = 0;
- else
- len = lastlen-priv->rx_prevlen;
-
- if (*(priv->rxringtail) & (1<<13)) {
- if ((*(priv->rxringtail) & 0xfff) < 500)
- priv->stats.rxcrcerrmin++;
- else if ((*(priv->rxringtail) & 0x0fff) > 1000)
- priv->stats.rxcrcerrmax++;
- else
- priv->stats.rxcrcerrmid++;
-
- }
-
- } else {
- len = priv->rxbuffersize;
- }
-
- if (first && last) {
- padding = ((*(priv->rxringtail+3))&(0x04000000))>>26;
- } else if (first) {
- padding = ((*(priv->rxringtail+3))&(0x04000000))>>26;
- if (padding)
- len -= 2;
- } else {
- padding = 0;
- }
- padding = 0;
- priv->rx_prevlen += len;
-
- if (priv->rx_prevlen > MAX_FRAG_THRESHOLD + 100) {
- /* HW is probably passing several buggy frames without
- * FD or LD flag set.
- * Throw this garbage away to prevent skb memory
- * exhausting
- */
- if (!priv->rx_skb_complete)
- dev_kfree_skb_any(priv->rx_skb);
- priv->rx_skb_complete = 1;
- }
-
- signal = (unsigned char)((*(priv->rxringtail + 3) &
- 0x00ff0000) >> 16);
- signal = (signal & 0xfe) >> 1;
-
- quality = (unsigned char)((*(priv->rxringtail+3)) & (0xff));
-
- stats.mac_time[0] = *(priv->rxringtail+1);
- stats.mac_time[1] = *(priv->rxringtail+2);
-
- rxpower = ((char)((*(priv->rxringtail + 4) &
- 0x00ff0000) >> 16)) / 2 - 42;
-
- RSSI = ((u8)((*(priv->rxringtail + 3) &
- 0x0000ff00) >> 8)) & 0x7f;
-
- rate = ((*(priv->rxringtail)) &
- ((1<<23)|(1<<22)|(1<<21)|(1<<20)))>>20;
-
- stats.rate = rtl8180_rate2rate(rate);
- Antenna = (*(priv->rxringtail + 3) & 0x00008000) == 0 ? 0 : 1;
- if (!rtl8180_IsWirelessBMode(stats.rate)) { /* OFDM rate. */
- RxAGC_dBm = rxpower+1; /* bias */
- } else { /* CCK rate. */
- RxAGC_dBm = signal; /* bit 0 discard */
-
- LNA = (u8) (RxAGC_dBm & 0x60) >> 5; /* bit 6~ bit 5 */
- BB = (u8) (RxAGC_dBm & 0x1F); /* bit 4 ~ bit 0 */
-
- /* Pin_11b=-(LNA_gain+BB_gain) (dBm) */
- RxAGC_dBm = -(LNA_gain[LNA] + (BB * 2));
-
- RxAGC_dBm += 4; /* bias */
- }
-
- if (RxAGC_dBm & 0x80) /* absolute value */
- RXAGC = ~(RxAGC_dBm)+1;
- bCckRate = rtl8180_IsWirelessBMode(stats.rate);
- /* Translate RXAGC into 1-100. */
- if (!rtl8180_IsWirelessBMode(stats.rate)) { /* OFDM rate. */
- if (RXAGC > 90)
- RXAGC = 90;
- else if (RXAGC < 25)
- RXAGC = 25;
- RXAGC = (90-RXAGC)*100/65;
- } else { /* CCK rate. */
- if (RXAGC > 95)
- RXAGC = 95;
- else if (RXAGC < 30)
- RXAGC = 30;
- RXAGC = (95-RXAGC)*100/65;
- }
- priv->SignalStrength = (u8)RXAGC;
- priv->RecvSignalPower = RxAGC_dBm;
- priv->RxPower = rxpower;
- priv->RSSI = RSSI;
- /* SQ translation formula is provided by SD3 DZ. 2006.06.27 */
- if (quality >= 127)
- /* 0 causes epc to show signal zero, walk around now */
- quality = 1;
- else if (quality < 27)
- quality = 100;
- else
- quality = 127 - quality;
- priv->SignalQuality = quality;
-
- stats.signal = (u8) quality;
-
- stats.signalstrength = RXAGC;
- if (stats.signalstrength > 100)
- stats.signalstrength = 100;
- stats.signalstrength = (stats.signalstrength * 70) / 100 + 30;
- stats.rssi = priv->wstats.qual.qual = priv->SignalQuality;
- stats.noise = priv->wstats.qual.noise =
- 100 - priv->wstats.qual.qual;
- bHwError = (((*(priv->rxringtail)) & (0x00000fff)) == 4080) |
- (((*(priv->rxringtail)) & (0x04000000)) != 0) |
- (((*(priv->rxringtail)) & (0x08000000)) != 0) |
- (((~(*(priv->rxringtail))) & (0x10000000)) != 0) |
- (((~(*(priv->rxringtail))) & (0x20000000)) != 0);
- bCRC = ((*(priv->rxringtail)) & (0x00002000)) >> 13;
- bICV = ((*(priv->rxringtail)) & (0x00001000)) >> 12;
- hdr = (struct ieee80211_hdr_4addr *)priv->rxbuffer->buf;
- fc = le16_to_cpu(hdr->frame_ctl);
- type = WLAN_FC_GET_TYPE(fc);
-
- if (IEEE80211_FTYPE_CTL != type &&
- !bHwError && !bCRC && !bICV &&
- eqMacAddr(priv->ieee80211->current_network.bssid,
- fc & IEEE80211_FCTL_TODS ? hdr->addr1 :
- fc & IEEE80211_FCTL_FROMDS ? hdr->addr2 :
- hdr->addr3)) {
-
- /* Perform signal smoothing for dynamic
- * mechanism on demand. This is different
- * with PerformSignalSmoothing8185 in smoothing
- * fomula. No dramatic adjustion is apply
- * because dynamic mechanism need some degree
- * of correctness. */
- PerformUndecoratedSignalSmoothing8185(priv, bCckRate);
-
- /* For good-looking singal strength. */
- SignalStrengthIndex = NetgearSignalStrengthTranslate(
- priv->LastSignalStrengthInPercent,
- priv->SignalStrength);
-
- priv->LastSignalStrengthInPercent = SignalStrengthIndex;
- priv->Stats_SignalStrength =
- TranslateToDbm8185((u8)SignalStrengthIndex);
-
- /*
- * We need more correct power of received packets and
- * the "SignalStrength" of RxStats is beautified, so we
- * record the correct power here.
- */
-
- priv->Stats_SignalQuality = (long)(
- priv->Stats_SignalQuality * 5 +
- (long)priv->SignalQuality + 5) / 6;
-
- priv->Stats_RecvSignalPower = (long)(
- priv->Stats_RecvSignalPower * 5 +
- priv->RecvSignalPower - 1) / 6;
-
- /*
- * Figure out which antenna received the last packet.
- * 0: aux, 1: main
- */
- priv->LastRxPktAntenna = Antenna ? 1 : 0;
- SwAntennaDiversityRxOk8185(dev, priv->SignalStrength);
- }
-
- if (first) {
- if (!priv->rx_skb_complete) {
- /* seems that HW sometimes fails to receive and
- * doesn't provide the last descriptor.
- */
- dev_kfree_skb_any(priv->rx_skb);
- priv->stats.rxnolast++;
- }
- priv->rx_skb = dev_alloc_skb(len+2);
- if (!priv->rx_skb)
- goto drop;
-
- priv->rx_skb_complete = 0;
- priv->rx_skb->dev = dev;
- } else {
- /* if we are here we should have already RXed the first
- * frame.
- * If we get here and the skb is not allocated then
- * we have just throw out garbage (skb not allocated)
- * and we are still rxing garbage....
- */
- if (!priv->rx_skb_complete) {
-
- tmp_skb = dev_alloc_skb(
- priv->rx_skb->len + len + 2);
-
- if (!tmp_skb)
- goto drop;
-
- tmp_skb->dev = dev;
-
- memcpy(skb_put(tmp_skb, priv->rx_skb->len),
- priv->rx_skb->data,
- priv->rx_skb->len);
-
- dev_kfree_skb_any(priv->rx_skb);
-
- priv->rx_skb = tmp_skb;
- }
- }
-
- if (!priv->rx_skb_complete) {
- memcpy(skb_put(priv->rx_skb, len), ((unsigned char *)
- priv->rxbuffer->buf) + (padding ? 2 : 0), len);
- }
-
- if (last && !priv->rx_skb_complete) {
- if (priv->rx_skb->len > 4)
- skb_trim(priv->rx_skb, priv->rx_skb->len-4);
- if (!ieee80211_rtl_rx(priv->ieee80211,
- priv->rx_skb, &stats))
- dev_kfree_skb_any(priv->rx_skb);
- priv->rx_skb_complete = 1;
- }
-
- pci_dma_sync_single_for_device(priv->pdev,
- priv->rxbuffer->dma,
- priv->rxbuffersize * sizeof(u8),
- PCI_DMA_FROMDEVICE);
-
-drop: /* this is used when we have not enough mem */
- /* restore the descriptor */
- *(priv->rxringtail+2) = priv->rxbuffer->dma;
- *(priv->rxringtail) = *(priv->rxringtail) & ~0xfff;
- *(priv->rxringtail) =
- *(priv->rxringtail) | priv->rxbuffersize;
-
- *(priv->rxringtail) =
- *(priv->rxringtail) | (1<<31);
-
- priv->rxringtail += rx_desc_size;
- if (priv->rxringtail >=
- (priv->rxring)+(priv->rxringcount)*rx_desc_size)
- priv->rxringtail = priv->rxring;
-
- priv->rxbuffer = (priv->rxbuffer->next);
- }
-}
-
-
-static void rtl8180_dma_kick(struct net_device *dev, int priority)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
- rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
- write_nic_byte(dev, TX_DMA_POLLING,
- (1 << (priority + 1)) | priv->dma_poll_mask);
- rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
-
- force_pci_posting(dev);
-}
-
-static void rtl8180_data_hard_stop(struct net_device *dev)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
- rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
- priv->dma_poll_stop_mask |= TPPOLLSTOP_AC_VIQ;
- write_nic_byte(dev, TPPollStop, priv->dma_poll_stop_mask);
- rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
-}
-
-static void rtl8180_data_hard_resume(struct net_device *dev)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
- rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
- priv->dma_poll_stop_mask &= ~(TPPOLLSTOP_AC_VIQ);
- write_nic_byte(dev, TPPollStop, priv->dma_poll_stop_mask);
- rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
-}
-
-/*
- * This function TX data frames when the ieee80211 stack requires this.
- * It checks also if we need to stop the ieee tx queue, eventually do it
- */
-static void rtl8180_hard_data_xmit(struct sk_buff *skb, struct net_device *dev,
- int rate)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- int mode;
- struct ieee80211_hdr_3addr *h = (struct ieee80211_hdr_3addr *)skb->data;
- bool morefrag = le16_to_cpu(h->frame_control) & IEEE80211_FCTL_MOREFRAGS;
- unsigned long flags;
- int priority;
-
- mode = priv->ieee80211->iw_mode;
-
- rate = ieeerate2rtlrate(rate);
- /*
- * This function doesn't require lock because we make sure it's called
- * with the tx_lock already acquired.
- * This come from the kernel's hard_xmit callback (through the ieee
- * stack, or from the try_wake_queue (again through the ieee stack.
- */
- priority = AC2Q(skb->priority);
- spin_lock_irqsave(&priv->tx_lock, flags);
-
- if (priv->ieee80211->bHwRadioOff) {
- spin_unlock_irqrestore(&priv->tx_lock, flags);
-
- return;
- }
-
- if (!check_nic_enought_desc(dev, priority)) {
- DMESGW("Error: no descriptor left by previous TX (avail %d) ",
- get_curr_tx_free_desc(dev, priority));
- ieee80211_rtl_stop_queue(priv->ieee80211);
- }
- rtl8180_tx(dev, skb->data, skb->len, priority, morefrag, 0, rate);
- if (!check_nic_enought_desc(dev, priority))
- ieee80211_rtl_stop_queue(priv->ieee80211);
-
- spin_unlock_irqrestore(&priv->tx_lock, flags);
-}
-
-/*
- * This is a rough attempt to TX a frame
- * This is called by the ieee 80211 stack to TX management frames.
- * If the ring is full packets are dropped (for data frame the queue
- * is stopped before this can happen). For this reason it is better
- * if the descriptors are larger than the largest management frame
- * we intend to TX: i'm unsure what the HW does if it will not find
- * the last fragment of a frame because it has been dropped...
- * Since queues for Management and Data frames are different we
- * might use a different lock than tx_lock (for example mgmt_tx_lock)
- */
-/* these function may loop if invoked with 0 descriptors or 0 len buffer */
-static int rtl8180_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- unsigned long flags;
- int priority;
-
- priority = MANAGE_PRIORITY;
-
- spin_lock_irqsave(&priv->tx_lock, flags);
-
- if (priv->ieee80211->bHwRadioOff) {
- spin_unlock_irqrestore(&priv->tx_lock, flags);
- dev_kfree_skb_any(skb);
- return NETDEV_TX_OK;
- }
-
- rtl8180_tx(dev, skb->data, skb->len, priority,
- 0, 0, ieeerate2rtlrate(priv->ieee80211->basic_rate));
-
- priv->ieee80211->stats.tx_bytes += skb->len;
- priv->ieee80211->stats.tx_packets++;
- spin_unlock_irqrestore(&priv->tx_lock, flags);
-
- dev_kfree_skb_any(skb);
- return NETDEV_TX_OK;
-}
-
-static void rtl8180_prepare_beacon(struct net_device *dev)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- struct sk_buff *skb;
-
- u16 word = read_nic_word(dev, BcnItv);
- word &= ~BcnItv_BcnItv; /* clear Bcn_Itv */
-
- /* word |= 0x64; */
- word |= cpu_to_le16(priv->ieee80211->current_network.beacon_interval);
-
- write_nic_word(dev, BcnItv, word);
-
- skb = ieee80211_get_beacon(priv->ieee80211);
- if (skb) {
- rtl8180_tx(dev, skb->data, skb->len, BEACON_PRIORITY,
- 0, 0, ieeerate2rtlrate(priv->ieee80211->basic_rate));
- dev_kfree_skb_any(skb);
- }
-}
-
-/*
- * This function do the real dirty work: it enqueues a TX command descriptor in
- * the ring buffer, copyes the frame in a TX buffer and kicks the NIC to ensure
- * it does the DMA transfer.
- */
-short rtl8180_tx(struct net_device *dev, u8 *txbuf, int len, int priority,
- bool morefrag, short descfrag, int rate)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- u32 *tail, *temp_tail;
- u32 *begin;
- u32 *buf;
- int i;
- int remain;
- int buflen;
- int count;
- struct buffer *buflist;
- struct ieee80211_hdr_3addr *frag_hdr =
- (struct ieee80211_hdr_3addr *)txbuf;
- u8 dest[ETH_ALEN];
- u8 bUseShortPreamble = 0;
- u8 bCTSEnable = 0;
- u8 bRTSEnable = 0;
- u16 Duration = 0;
- u16 RtsDur = 0;
- u16 ThisFrameTime = 0;
- u16 TxDescDuration = 0;
- bool ownbit_flag = false;
-
- switch (priority) {
- case MANAGE_PRIORITY:
- tail = priv->txmapringtail;
- begin = priv->txmapring;
- buflist = priv->txmapbufstail;
- count = priv->txringcount;
- break;
- case BK_PRIORITY:
- tail = priv->txbkpringtail;
- begin = priv->txbkpring;
- buflist = priv->txbkpbufstail;
- count = priv->txringcount;
- break;
- case BE_PRIORITY:
- tail = priv->txbepringtail;
- begin = priv->txbepring;
- buflist = priv->txbepbufstail;
- count = priv->txringcount;
- break;
- case VI_PRIORITY:
- tail = priv->txvipringtail;
- begin = priv->txvipring;
- buflist = priv->txvipbufstail;
- count = priv->txringcount;
- break;
- case VO_PRIORITY:
- tail = priv->txvopringtail;
- begin = priv->txvopring;
- buflist = priv->txvopbufstail;
- count = priv->txringcount;
- break;
- case HI_PRIORITY:
- tail = priv->txhpringtail;
- begin = priv->txhpring;
- buflist = priv->txhpbufstail;
- count = priv->txringcount;
- break;
- case BEACON_PRIORITY:
- tail = priv->txbeaconringtail;
- begin = priv->txbeaconring;
- buflist = priv->txbeaconbufstail;
- count = priv->txbeaconcount;
- break;
- default:
- return -1;
- break;
- }
-
- memcpy(&dest, frag_hdr->addr1, ETH_ALEN);
- if (is_multicast_ether_addr(dest)) {
- Duration = 0;
- RtsDur = 0;
- bRTSEnable = 0;
- bCTSEnable = 0;
-
- ThisFrameTime = ComputeTxTime(len + sCrcLng,
- rtl8180_rate2rate(rate), 0, bUseShortPreamble);
- TxDescDuration = ThisFrameTime;
- } else { /* Unicast packet */
- u16 AckTime;
-
- /* for Keep alive */
- priv->NumTxUnicast++;
-
- /* Figure out ACK rate according to BSS basic rate
- * and Tx rate.
- * AckCTSLng = 14 use 1M bps send
- */
- AckTime = ComputeTxTime(14, 10, 0, 0);
-
- if (((len + sCrcLng) > priv->rts) && priv->rts) { /* RTS/CTS. */
- u16 RtsTime, CtsTime;
- bRTSEnable = 1;
- bCTSEnable = 0;
-
- /* Rate and time required for RTS. */
- RtsTime = ComputeTxTime(sAckCtsLng / 8,
- priv->ieee80211->basic_rate, 0, 0);
-
- /* Rate and time required for CTS.
- * AckCTSLng = 14 use 1M bps send
- */
- CtsTime = ComputeTxTime(14, 10, 0, 0);
-
- /* Figure out time required to transmit this frame. */
- ThisFrameTime = ComputeTxTime(len + sCrcLng,
- rtl8180_rate2rate(rate), 0,
- bUseShortPreamble);
-
- /* RTS-CTS-ThisFrame-ACK. */
- RtsDur = CtsTime + ThisFrameTime +
- AckTime + 3 * aSifsTime;
-
- TxDescDuration = RtsTime + RtsDur;
- } else { /* Normal case. */
- bCTSEnable = 0;
- bRTSEnable = 0;
- RtsDur = 0;
-
- ThisFrameTime = ComputeTxTime(len + sCrcLng,
- rtl8180_rate2rate(rate), 0, bUseShortPreamble);
- TxDescDuration = ThisFrameTime + aSifsTime + AckTime;
- }
-
- if (!(le16_to_cpu(frag_hdr->frame_control) & IEEE80211_FCTL_MOREFRAGS)) {
- /* ThisFrame-ACK. */
- Duration = aSifsTime + AckTime;
- } else { /* One or more fragments remained. */
- u16 NextFragTime;
-
- /* pretend following packet length = current packet */
- NextFragTime = ComputeTxTime(len + sCrcLng,
- rtl8180_rate2rate(rate), 0, bUseShortPreamble);
-
- /* ThisFrag-ACk-NextFrag-ACK. */
- Duration = NextFragTime + 3 * aSifsTime + 2 * AckTime;
- }
-
- } /* End of Unicast packet */
-
- frag_hdr->duration_id = Duration;
-
- buflen = priv->txbuffsize;
- remain = len;
- temp_tail = tail;
-
- while (remain != 0) {
- mb();
- if (!buflist) {
- DMESGE("TX buffer error, cannot TX frames. pri %d.",
- priority);
- return -1;
- }
- buf = buflist->buf;
-
- if ((*tail & (1 << 31)) && (priority != BEACON_PRIORITY)) {
- DMESGW("No more TX desc, returning %x of %x",
- remain, len);
- priv->stats.txrdu++;
- return remain;
- }
-
- *tail = 0; /* zeroes header */
- *(tail+1) = 0;
- *(tail+3) = 0;
- *(tail+5) = 0;
- *(tail+6) = 0;
- *(tail+7) = 0;
-
- /* FIXME: should be triggered by HW encryption parameters.*/
- *tail |= (1<<15); /* no encrypt */
-
- if (remain == len && !descfrag) {
- ownbit_flag = false;
- *tail = *tail | (1 << 29); /* first segment of packet */
- *tail = *tail | (len);
- } else {
- ownbit_flag = true;
- }
-
- for (i = 0; i < buflen && remain > 0; i++, remain--) {
- /* copy data into descriptor pointed DMAble buffer */
- ((u8 *)buf)[i] = txbuf[i];
-
- if (remain == 4 && i+4 >= buflen)
- break;
- /* ensure the last desc has at least 4 bytes payload */
- }
- txbuf = txbuf + i;
- *(tail+3) = *(tail+3) & ~0xfff;
- *(tail+3) = *(tail+3) | i; /* buffer length */
-
- if (bCTSEnable)
- *tail |= (1<<18);
-
- if (bRTSEnable) { /* rts enable */
- /* RTS RATE */
- *tail |= (ieeerate2rtlrate(
- priv->ieee80211->basic_rate) << 19);
-
- *tail |= (1<<23); /* rts enable */
- *(tail+1) |= (RtsDur&0xffff); /* RTS Duration */
- }
- *(tail+3) |= ((TxDescDuration&0xffff)<<16); /* DURATION */
-
- *(tail + 5) |= (11 << 8); /* retry lim; */
-
- *tail = *tail | ((rate&0xf) << 24);
-
- if (morefrag)
- *tail = (*tail) | (1<<17); /* more fragment */
- if (!remain)
- *tail = (*tail) | (1<<28); /* last segment of frame */
-
- *(tail+5) = *(tail+5)|(2<<27);
- *(tail+7) = *(tail+7)|(1<<4);
-
- wmb();
- if (ownbit_flag)
- /* descriptor ready to be txed */
- *tail |= (1 << 31);
-
- if ((tail - begin)/8 == count-1)
- tail = begin;
- else
- tail = tail+8;
-
- buflist = buflist->next;
-
- mb();
-
- switch (priority) {
- case MANAGE_PRIORITY:
- priv->txmapringtail = tail;
- priv->txmapbufstail = buflist;
- break;
- case BK_PRIORITY:
- priv->txbkpringtail = tail;
- priv->txbkpbufstail = buflist;
- break;
- case BE_PRIORITY:
- priv->txbepringtail = tail;
- priv->txbepbufstail = buflist;
- break;
- case VI_PRIORITY:
- priv->txvipringtail = tail;
- priv->txvipbufstail = buflist;
- break;
- case VO_PRIORITY:
- priv->txvopringtail = tail;
- priv->txvopbufstail = buflist;
- break;
- case HI_PRIORITY:
- priv->txhpringtail = tail;
- priv->txhpbufstail = buflist;
- break;
- case BEACON_PRIORITY:
- /*
- * The HW seems to be happy with the 1st
- * descriptor filled and the 2nd empty...
- * So always update descriptor 1 and never
- * touch 2nd
- */
- break;
- }
- }
- *temp_tail = *temp_tail | (1<<31); /* descriptor ready to be txed */
- rtl8180_dma_kick(dev, priority);
-
- return 0;
-}
-
-void rtl8180_irq_rx_tasklet(struct r8180_priv *priv);
-
-static void rtl8180_link_change(struct net_device *dev)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- u16 beacon_interval;
- struct ieee80211_network *net = &priv->ieee80211->current_network;
-
- rtl8180_update_msr(dev);
-
- rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
-
- write_nic_dword(dev, BSSID, ((u32 *)net->bssid)[0]);
- write_nic_word(dev, BSSID+4, ((u16 *)net->bssid)[2]);
-
- beacon_interval = read_nic_word(dev, BEACON_INTERVAL);
- beacon_interval &= ~BEACON_INTERVAL_MASK;
- beacon_interval |= net->beacon_interval;
- write_nic_word(dev, BEACON_INTERVAL, beacon_interval);
-
- rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
-
- rtl8180_set_chan(dev, priv->chan);
-}
-
-static void rtl8180_rq_tx_ack(struct net_device *dev)
-{
-
- struct r8180_priv *priv = ieee80211_priv(dev);
-
- write_nic_byte(dev, CONFIG4,
- read_nic_byte(dev, CONFIG4) | CONFIG4_PWRMGT);
- priv->ack_tx_to_ieee = 1;
-}
-
-static short rtl8180_is_tx_queue_empty(struct net_device *dev)
-{
-
- struct r8180_priv *priv = ieee80211_priv(dev);
- u32 *d;
-
- for (d = priv->txmapring;
- d < priv->txmapring + priv->txringcount; d += 8)
- if (*d & (1<<31))
- return 0;
-
- for (d = priv->txbkpring;
- d < priv->txbkpring + priv->txringcount; d += 8)
- if (*d & (1<<31))
- return 0;
-
- for (d = priv->txbepring;
- d < priv->txbepring + priv->txringcount; d += 8)
- if (*d & (1<<31))
- return 0;
-
- for (d = priv->txvipring;
- d < priv->txvipring + priv->txringcount; d += 8)
- if (*d & (1<<31))
- return 0;
-
- for (d = priv->txvopring;
- d < priv->txvopring + priv->txringcount; d += 8)
- if (*d & (1<<31))
- return 0;
-
- for (d = priv->txhpring;
- d < priv->txhpring + priv->txringcount; d += 8)
- if (*d & (1<<31))
- return 0;
- return 1;
-}
-
-static void rtl8180_hw_wakeup(struct net_device *dev)
-{
- unsigned long flags;
- struct r8180_priv *priv = ieee80211_priv(dev);
-
- spin_lock_irqsave(&priv->ps_lock, flags);
- write_nic_byte(dev, CONFIG4,
- read_nic_byte(dev, CONFIG4) & ~CONFIG4_PWRMGT);
- if (priv->rf_wakeup)
- priv->rf_wakeup(dev);
- spin_unlock_irqrestore(&priv->ps_lock, flags);
-}
-
-static void rtl8180_hw_sleep_down(struct net_device *dev)
-{
- unsigned long flags;
- struct r8180_priv *priv = ieee80211_priv(dev);
-
- spin_lock_irqsave(&priv->ps_lock, flags);
- if (priv->rf_sleep)
- priv->rf_sleep(dev);
- spin_unlock_irqrestore(&priv->ps_lock, flags);
-}
-
-static void rtl8180_hw_sleep(struct net_device *dev, u32 th, u32 tl)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- u32 rb = jiffies;
- unsigned long flags;
-
- spin_lock_irqsave(&priv->ps_lock, flags);
-
- /*
- * Writing HW register with 0 equals to disable
- * the timer, that is not really what we want
- */
- tl -= MSECS(4+16+7);
-
- /*
- * If the interval in which we are requested to sleep is too
- * short then give up and remain awake
- */
- if (((tl >= rb) && (tl-rb) <= MSECS(MIN_SLEEP_TIME))
- || ((rb > tl) && (rb-tl) < MSECS(MIN_SLEEP_TIME))) {
- spin_unlock_irqrestore(&priv->ps_lock, flags);
- netdev_warn(dev, "too short to sleep\n");
- return;
- }
-
- {
- u32 tmp = (tl > rb) ? (tl-rb) : (rb-tl);
-
- priv->DozePeriodInPast2Sec += jiffies_to_msecs(tmp);
- /* as tl may be less than rb */
- queue_delayed_work(priv->ieee80211->wq,
- &priv->ieee80211->hw_wakeup_wq, tmp);
- }
- /*
- * If we suspect the TimerInt is gone beyond tl
- * while setting it, then give up
- */
-
- if (((tl > rb) && ((tl-rb) > MSECS(MAX_SLEEP_TIME))) ||
- ((tl < rb) && ((rb-tl) > MSECS(MAX_SLEEP_TIME)))) {
- spin_unlock_irqrestore(&priv->ps_lock, flags);
- return;
- }
-
- queue_work(priv->ieee80211->wq, (void *)&priv->ieee80211->hw_sleep_wq);
- spin_unlock_irqrestore(&priv->ps_lock, flags);
-}
-
-static void rtl8180_wmm_single_param_update(struct net_device *dev,
- u8 mode, AC_CODING eACI, PAC_PARAM param)
-{
- u8 u1bAIFS;
- u32 u4bAcParam;
-
- /* Retrieve parameters to update. */
- /* Mode G/A: slotTimeTimer = 9; Mode B: 20 */
- u1bAIFS = param->f.AciAifsn.f.AIFSN * ((mode & IEEE_G) == IEEE_G ?
- 9 : 20) + aSifsTime;
- u4bAcParam = (((u32)param->f.TXOPLimit << AC_PARAM_TXOP_LIMIT_OFFSET) |
- ((u32)param->f.Ecw.f.ECWmax << AC_PARAM_ECW_MAX_OFFSET) |
- ((u32)param->f.Ecw.f.ECWmin << AC_PARAM_ECW_MIN_OFFSET) |
- ((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET));
-
- switch (eACI) {
- case AC1_BK:
- write_nic_dword(dev, AC_BK_PARAM, u4bAcParam);
- return;
- case AC0_BE:
- write_nic_dword(dev, AC_BE_PARAM, u4bAcParam);
- return;
- case AC2_VI:
- write_nic_dword(dev, AC_VI_PARAM, u4bAcParam);
- return;
- case AC3_VO:
- write_nic_dword(dev, AC_VO_PARAM, u4bAcParam);
- return;
- default:
- pr_warn("SetHwReg8185(): invalid ACI: %d!\n", eACI);
- return;
- }
-}
-
-static void rtl8180_wmm_param_update(struct work_struct *work)
-{
- struct ieee80211_device *ieee = container_of(work,
- struct ieee80211_device, wmm_param_update_wq);
- struct net_device *dev = ieee->dev;
- u8 *ac_param = (u8 *)(ieee->current_network.wmm_param);
- u8 mode = ieee->current_network.mode;
- AC_CODING eACI;
- AC_PARAM AcParam;
-
- if (!ieee->current_network.QoS_Enable) {
- /* legacy ac_xx_param update */
- AcParam.longData = 0;
- AcParam.f.AciAifsn.f.AIFSN = 2; /* Follow 802.11 DIFS. */
- AcParam.f.AciAifsn.f.ACM = 0;
- AcParam.f.Ecw.f.ECWmin = 3; /* Follow 802.11 CWmin. */
- AcParam.f.Ecw.f.ECWmax = 7; /* Follow 802.11 CWmax. */
- AcParam.f.TXOPLimit = 0;
-
- for (eACI = 0; eACI < AC_MAX; eACI++) {
- AcParam.f.AciAifsn.f.ACI = (u8)eACI;
-
- rtl8180_wmm_single_param_update(dev, mode, eACI,
- (PAC_PARAM)&AcParam);
- }
- return;
- }
-
- for (eACI = 0; eACI < AC_MAX; eACI++) {
- rtl8180_wmm_single_param_update(dev, mode,
- ((PAC_PARAM)ac_param)->f.AciAifsn.f.ACI,
- (PAC_PARAM)ac_param);
-
- ac_param += sizeof(AC_PARAM);
- }
-}
-
-void rtl8180_restart_wq(struct work_struct *work);
-void rtl8180_watch_dog_wq(struct work_struct *work);
-void rtl8180_hw_wakeup_wq(struct work_struct *work);
-void rtl8180_hw_sleep_wq(struct work_struct *work);
-void rtl8180_sw_antenna_wq(struct work_struct *work);
-void rtl8180_watch_dog(struct net_device *dev);
-
-static void watch_dog_adaptive(unsigned long data)
-{
- struct r8180_priv *priv = ieee80211_priv((struct net_device *)data);
-
- if (!priv->up) {
- DMESG("<----watch_dog_adaptive():driver is not up!\n");
- return;
- }
-
- /* Tx High Power Mechanism. */
- if (CheckHighPower((struct net_device *)data))
- queue_work(priv->ieee80211->wq,
- (void *)&priv->ieee80211->tx_pw_wq);
-
- /* Tx Power Tracking on 87SE. */
- if (CheckTxPwrTracking((struct net_device *)data))
- TxPwrTracking87SE((struct net_device *)data);
-
- /* Perform DIG immediately. */
- if (CheckDig((struct net_device *)data))
- queue_work(priv->ieee80211->wq,
- (void *)&priv->ieee80211->hw_dig_wq);
-
- rtl8180_watch_dog((struct net_device *)data);
-
- queue_work(priv->ieee80211->wq,
- (void *)&priv->ieee80211->GPIOChangeRFWorkItem);
-
- priv->watch_dog_timer.expires = jiffies +
- MSECS(IEEE80211_WATCH_DOG_TIME);
-
- add_timer(&priv->watch_dog_timer);
-}
-
-static struct rtl8187se_channel_list channel_plan_list[] = {
- /* FCC */
- {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 36, 40,
- 44, 48, 52, 56, 60, 64}, 19},
-
- /* IC */
- {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11},
-
- /* ETSI */
- {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40,
- 44, 48, 52, 56, 60, 64}, 21},
-
- /* Spain. Change to ETSI. */
- {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40,
- 44, 48, 52, 56, 60, 64}, 21},
-
- /* France. Change to ETSI. */
- {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40,
- 44, 48, 52, 56, 60, 64}, 21},
-
- /* MKK */
- {{14, 36, 40, 44, 48, 52, 56, 60, 64}, 9},
-
- /* MKK1 */
- {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36,
- 40, 44, 48, 52, 56, 60, 64}, 22},
-
- /* Israel. */
- {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40,
- 44, 48, 52, 56, 60, 64}, 21},
-
- /* For 11a , TELEC */
- {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 34, 38, 42, 46}, 17},
-
- /* For Global Domain. 1-11 active, 12-14 passive. */
- {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14},
-
- /* world wide 13: ch1~ch11 active, ch12~13 passive */
- {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}
-};
-
-static void rtl8180_set_channel_map(u8 channel_plan,
- struct ieee80211_device *ieee)
-{
- int i;
-
- ieee->MinPassiveChnlNum = MAX_CHANNEL_NUMBER+1;
- ieee->IbssStartChnl = 0;
-
- switch (channel_plan) {
- case COUNTRY_CODE_FCC:
- case COUNTRY_CODE_IC:
- case COUNTRY_CODE_ETSI:
- case COUNTRY_CODE_SPAIN:
- case COUNTRY_CODE_FRANCE:
- case COUNTRY_CODE_MKK:
- case COUNTRY_CODE_MKK1:
- case COUNTRY_CODE_ISRAEL:
- case COUNTRY_CODE_TELEC:
- {
- Dot11d_Init(ieee);
- ieee->bGlobalDomain = false;
- if (channel_plan_list[channel_plan].len != 0) {
- /* Clear old channel map */
- memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map));
- /* Set new channel map */
- for (i = 0; i < channel_plan_list[channel_plan].len; i++) {
- if (channel_plan_list[channel_plan].channel[i] <= 14)
- GET_DOT11D_INFO(ieee)->channel_map[channel_plan_list[channel_plan].channel[i]] = 1;
- }
- }
- break;
- }
- case COUNTRY_CODE_GLOBAL_DOMAIN:
- {
- GET_DOT11D_INFO(ieee)->bEnabled = false;
- Dot11d_Reset(ieee);
- ieee->bGlobalDomain = true;
- break;
- }
- case COUNTRY_CODE_WORLD_WIDE_13_INDEX:
- {
- ieee->MinPassiveChnlNum = 12;
- ieee->IbssStartChnl = 10;
- break;
- }
- default:
- {
- Dot11d_Init(ieee);
- ieee->bGlobalDomain = false;
- memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map));
- for (i = 1; i <= 14; i++)
- GET_DOT11D_INFO(ieee)->channel_map[i] = 1;
- break;
- }
- }
-}
-
-void GPIOChangeRFWorkItemCallBack(struct work_struct *work);
-
-static void rtl8180_statistics_init(struct stats *pstats)
-{
- memset(pstats, 0, sizeof(struct stats));
-}
-
-static void rtl8180_link_detect_init(struct link_detect_t *plink_detect)
-{
- memset(plink_detect, 0, sizeof(struct link_detect_t));
- plink_detect->slot_num = DEFAULT_SLOT_NUM;
-}
-
-static void rtl8187se_eeprom_register_read(struct eeprom_93cx6 *eeprom)
-{
- struct net_device *dev = eeprom->data;
- u8 reg = read_nic_byte(dev, EPROM_CMD);
-
- eeprom->reg_data_in = reg & RTL818X_EEPROM_CMD_WRITE;
- eeprom->reg_data_out = reg & RTL818X_EEPROM_CMD_READ;
- eeprom->reg_data_clock = reg & RTL818X_EEPROM_CMD_CK;
- eeprom->reg_chip_select = reg & RTL818X_EEPROM_CMD_CS;
-}
-
-static void rtl8187se_eeprom_register_write(struct eeprom_93cx6 *eeprom)
-{
- struct net_device *dev = eeprom->data;
- u8 reg = 2 << 6;
-
- if (eeprom->reg_data_in)
- reg |= RTL818X_EEPROM_CMD_WRITE;
- if (eeprom->reg_data_out)
- reg |= RTL818X_EEPROM_CMD_READ;
- if (eeprom->reg_data_clock)
- reg |= RTL818X_EEPROM_CMD_CK;
- if (eeprom->reg_chip_select)
- reg |= RTL818X_EEPROM_CMD_CS;
-
- write_nic_byte(dev, EPROM_CMD, reg);
- read_nic_byte(dev, EPROM_CMD);
- udelay(10);
-}
-
-static short rtl8180_init(struct net_device *dev)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- u16 word;
- u16 usValue;
- u16 tmpu16;
- int i, j;
- struct eeprom_93cx6 eeprom;
- u16 eeprom_val;
-
- eeprom.data = dev;
- eeprom.register_read = rtl8187se_eeprom_register_read;
- eeprom.register_write = rtl8187se_eeprom_register_write;
- eeprom.width = PCI_EEPROM_WIDTH_93C46;
-
- eeprom_93cx6_read(&eeprom, EEPROM_COUNTRY_CODE>>1, &eeprom_val);
- priv->channel_plan = eeprom_val & 0xFF;
- if (priv->channel_plan > COUNTRY_CODE_GLOBAL_DOMAIN) {
- netdev_err(dev, "rtl8180_init: Invalid channel plan! Set to default.\n");
- priv->channel_plan = 0;
- }
-
- DMESG("Channel plan is %d\n", priv->channel_plan);
- rtl8180_set_channel_map(priv->channel_plan, priv->ieee80211);
-
- /* FIXME: these constants are placed in a bad pleace. */
- priv->txbuffsize = 2048; /* 1024; */
- priv->txringcount = 32; /* 32; */
- priv->rxbuffersize = 2048; /* 1024; */
- priv->rxringcount = 64; /* 32; */
- priv->txbeaconcount = 2;
- priv->rx_skb_complete = 1;
-
- priv->RFChangeInProgress = false;
- priv->SetRFPowerStateInProgress = false;
- priv->RFProgType = 0;
-
- priv->irq_enabled = 0;
-
- rtl8180_statistics_init(&priv->stats);
- rtl8180_link_detect_init(&priv->link_detect);
-
- priv->ack_tx_to_ieee = 0;
- priv->ieee80211->current_network.beacon_interval =
- DEFAULT_BEACONINTERVAL;
- priv->ieee80211->iw_mode = IW_MODE_INFRA;
- priv->ieee80211->softmac_features = IEEE_SOFTMAC_SCAN |
- IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ |
- IEEE_SOFTMAC_PROBERS | IEEE_SOFTMAC_TX_QUEUE;
- priv->ieee80211->active_scan = 1;
- priv->ieee80211->rate = 110; /* 11 mbps */
- priv->ieee80211->modulation = IEEE80211_CCK_MODULATION;
- priv->ieee80211->host_encrypt = 1;
- priv->ieee80211->host_decrypt = 1;
- priv->ieee80211->sta_wake_up = rtl8180_hw_wakeup;
- priv->ieee80211->ps_request_tx_ack = rtl8180_rq_tx_ack;
- priv->ieee80211->enter_sleep_state = rtl8180_hw_sleep;
- priv->ieee80211->ps_is_queue_empty = rtl8180_is_tx_queue_empty;
-
- priv->hw_wep = hwwep;
- priv->dev = dev;
- priv->retry_rts = DEFAULT_RETRY_RTS;
- priv->retry_data = DEFAULT_RETRY_DATA;
- priv->RFChangeInProgress = false;
- priv->SetRFPowerStateInProgress = false;
- priv->RFProgType = 0;
- priv->bInactivePs = true; /* false; */
- priv->ieee80211->bInactivePs = priv->bInactivePs;
- priv->bSwRfProcessing = false;
- priv->eRFPowerState = RF_OFF;
- priv->RfOffReason = 0;
- priv->led_strategy = SW_LED_MODE0;
- priv->TxPollingTimes = 0;
- priv->bLeisurePs = true;
- priv->dot11PowerSaveMode = ACTIVE;
- priv->AdMinCheckPeriod = 5;
- priv->AdMaxCheckPeriod = 10;
- priv->AdMaxRxSsThreshold = 30; /* 60->30 */
- priv->AdRxSsThreshold = 20; /* 50->20 */
- priv->AdCheckPeriod = priv->AdMinCheckPeriod;
- priv->AdTickCount = 0;
- priv->AdRxSignalStrength = -1;
- priv->RegSwAntennaDiversityMechanism = 0;
- priv->RegDefaultAntenna = 0;
- priv->SignalStrength = 0;
- priv->AdRxOkCnt = 0;
- priv->CurrAntennaIndex = 0;
- priv->AdRxSsBeforeSwitched = 0;
- init_timer(&priv->SwAntennaDiversityTimer);
- priv->SwAntennaDiversityTimer.data = (unsigned long)dev;
- priv->SwAntennaDiversityTimer.function =
- (void *)SwAntennaDiversityTimerCallback;
- priv->bDigMechanism = true;
- priv->InitialGain = 6;
- priv->bXtalCalibration = false;
- priv->XtalCal_Xin = 0;
- priv->XtalCal_Xout = 0;
- priv->bTxPowerTrack = false;
- priv->ThermalMeter = 0;
- priv->FalseAlarmRegValue = 0;
- priv->RegDigOfdmFaUpTh = 0xc; /* Upper threshold of OFDM false alarm,
- which is used in DIG. */
- priv->DIG_NumberFallbackVote = 0;
- priv->DIG_NumberUpgradeVote = 0;
- priv->LastSignalStrengthInPercent = 0;
- priv->Stats_SignalStrength = 0;
- priv->LastRxPktAntenna = 0;
- priv->SignalQuality = 0; /* in 0-100 index. */
- priv->Stats_SignalQuality = 0;
- priv->RecvSignalPower = 0; /* in dBm. */
- priv->Stats_RecvSignalPower = 0;
- priv->AdMainAntennaRxOkCnt = 0;
- priv->AdAuxAntennaRxOkCnt = 0;
- priv->bHWAdSwitched = false;
- priv->bRegHighPowerMechanism = true;
- priv->RegHiPwrUpperTh = 77;
- priv->RegHiPwrLowerTh = 75;
- priv->RegRSSIHiPwrUpperTh = 70;
- priv->RegRSSIHiPwrLowerTh = 20;
- priv->bCurCCKPkt = false;
- priv->UndecoratedSmoothedSS = -1;
- priv->bToUpdateTxPwr = false;
- priv->CurCCKRSSI = 0;
- priv->RxPower = 0;
- priv->RSSI = 0;
- priv->NumTxOkTotal = 0;
- priv->NumTxUnicast = 0;
- priv->keepAliveLevel = DEFAULT_KEEP_ALIVE_LEVEL;
- priv->CurrRetryCnt = 0;
- priv->LastRetryCnt = 0;
- priv->LastTxokCnt = 0;
- priv->LastRxokCnt = 0;
- priv->LastRetryRate = 0;
- priv->bTryuping = 0;
- priv->CurrTxRate = 0;
- priv->CurrRetryRate = 0;
- priv->TryupingCount = 0;
- priv->TryupingCountNoData = 0;
- priv->TryDownCountLowData = 0;
- priv->LastTxOKBytes = 0;
- priv->LastFailTxRate = 0;
- priv->LastFailTxRateSS = 0;
- priv->FailTxRateCount = 0;
- priv->LastTxThroughput = 0;
- priv->NumTxOkBytesTotal = 0;
- priv->ForcedDataRate = 0;
- priv->RegBModeGainStage = 1;
-
- priv->promisc = (dev->flags & IFF_PROMISC) ? 1 : 0;
- spin_lock_init(&priv->irq_th_lock);
- spin_lock_init(&priv->tx_lock);
- spin_lock_init(&priv->ps_lock);
- spin_lock_init(&priv->rf_ps_lock);
- sema_init(&priv->wx_sem, 1);
- INIT_WORK(&priv->reset_wq, (void *)rtl8180_restart_wq);
- INIT_DELAYED_WORK(&priv->ieee80211->hw_wakeup_wq,
- (void *)rtl8180_hw_wakeup_wq);
- INIT_DELAYED_WORK(&priv->ieee80211->hw_sleep_wq,
- (void *)rtl8180_hw_sleep_wq);
- INIT_WORK(&priv->ieee80211->wmm_param_update_wq,
- (void *)rtl8180_wmm_param_update);
- INIT_DELAYED_WORK(&priv->ieee80211->rate_adapter_wq,
- (void *)rtl8180_rate_adapter);
- INIT_DELAYED_WORK(&priv->ieee80211->hw_dig_wq,
- (void *)rtl8180_hw_dig_wq);
- INIT_DELAYED_WORK(&priv->ieee80211->tx_pw_wq,
- (void *)rtl8180_tx_pw_wq);
- INIT_DELAYED_WORK(&priv->ieee80211->GPIOChangeRFWorkItem,
- (void *) GPIOChangeRFWorkItemCallBack);
- tasklet_init(&priv->irq_rx_tasklet,
- (void(*)(unsigned long)) rtl8180_irq_rx_tasklet,
- (unsigned long)priv);
-
- init_timer(&priv->watch_dog_timer);
- priv->watch_dog_timer.data = (unsigned long)dev;
- priv->watch_dog_timer.function = watch_dog_adaptive;
-
- init_timer(&priv->rateadapter_timer);
- priv->rateadapter_timer.data = (unsigned long)dev;
- priv->rateadapter_timer.function = timer_rate_adaptive;
- priv->RateAdaptivePeriod = RATE_ADAPTIVE_TIMER_PERIOD;
- priv->bEnhanceTxPwr = false;
-
- priv->ieee80211->softmac_hard_start_xmit = rtl8180_hard_start_xmit;
- priv->ieee80211->set_chan = rtl8180_set_chan;
- priv->ieee80211->link_change = rtl8180_link_change;
- priv->ieee80211->softmac_data_hard_start_xmit = rtl8180_hard_data_xmit;
- priv->ieee80211->data_hard_stop = rtl8180_data_hard_stop;
- priv->ieee80211->data_hard_resume = rtl8180_data_hard_resume;
-
- priv->ieee80211->init_wmmparam_flag = 0;
-
- priv->ieee80211->start_send_beacons = rtl8180_start_tx_beacon;
- priv->ieee80211->stop_send_beacons = rtl8180_beacon_tx_disable;
- priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
-
- priv->ShortRetryLimit = 7;
- priv->LongRetryLimit = 7;
- priv->EarlyRxThreshold = 7;
-
- priv->TransmitConfig = (1<<TCR_DurProcMode_OFFSET) |
- (7<<TCR_MXDMA_OFFSET) |
- (priv->ShortRetryLimit<<TCR_SRL_OFFSET) |
- (priv->LongRetryLimit<<TCR_LRL_OFFSET);
-
- priv->ReceiveConfig = RCR_AMF | RCR_ADF | RCR_ACF |
- RCR_AB | RCR_AM | RCR_APM |
- (7<<RCR_MXDMA_OFFSET) |
- (priv->EarlyRxThreshold<<RCR_FIFO_OFFSET) |
- (priv->EarlyRxThreshold == 7 ?
- RCR_ONLYERLPKT : 0);
-
- priv->IntrMask = IMR_TMGDOK | IMR_TBDER |
- IMR_THPDER | IMR_THPDOK |
- IMR_TVODER | IMR_TVODOK |
- IMR_TVIDER | IMR_TVIDOK |
- IMR_TBEDER | IMR_TBEDOK |
- IMR_TBKDER | IMR_TBKDOK |
- IMR_RDU |
- IMR_RER | IMR_ROK |
- IMR_RQoSOK;
-
- priv->InitialGain = 6;
-
- DMESG("MAC controller is a RTL8187SE b/g");
-
- priv->ieee80211->modulation |= IEEE80211_OFDM_MODULATION;
- priv->ieee80211->short_slot = 1;
-
- eeprom_93cx6_read(&eeprom, EEPROM_SW_REVD_OFFSET, &usValue);
- DMESG("usValue is %#hx\n", usValue);
- /* 3Read AntennaDiversity */
-
- /* SW Antenna Diversity. */
- priv->EEPROMSwAntennaDiversity = (usValue & EEPROM_SW_AD_MASK) ==
- EEPROM_SW_AD_ENABLE;
-
- /* Default Antenna to use. */
- priv->EEPROMDefaultAntenna1 = (usValue & EEPROM_DEF_ANT_MASK) ==
- EEPROM_DEF_ANT_1;
-
- if (priv->RegSwAntennaDiversityMechanism == 0) /* Auto */
- /* 0: default from EEPROM. */
- priv->bSwAntennaDiverity = priv->EEPROMSwAntennaDiversity;
- else
- /* 1:disable antenna diversity, 2: enable antenna diversity. */
- priv->bSwAntennaDiverity =
- priv->RegSwAntennaDiversityMechanism == 2;
-
- if (priv->RegDefaultAntenna == 0)
- /* 0: default from EEPROM. */
- priv->bDefaultAntenna1 = priv->EEPROMDefaultAntenna1;
- else
- /* 1: main, 2: aux. */
- priv->bDefaultAntenna1 = priv->RegDefaultAntenna == 2;
-
- priv->plcp_preamble_mode = 2;
- /* the eeprom type is stored in RCR register bit #6 */
- if (RCR_9356SEL & read_nic_dword(dev, RCR))
- priv->epromtype = EPROM_93c56;
- else
- priv->epromtype = EPROM_93c46;
-
- eeprom_93cx6_multiread(&eeprom, 0x7, (__le16 *)
- dev->dev_addr, 3);
-
- for (i = 1, j = 0; i < 14; i += 2, j++) {
- eeprom_93cx6_read(&eeprom, EPROM_TXPW_CH1_2 + j, &word);
- priv->chtxpwr[i] = word & 0xff;
- priv->chtxpwr[i+1] = (word & 0xff00)>>8;
- }
- for (i = 1, j = 0; i < 14; i += 2, j++) {
- eeprom_93cx6_read(&eeprom, EPROM_TXPW_OFDM_CH1_2 + j, &word);
- priv->chtxpwr_ofdm[i] = word & 0xff;
- priv->chtxpwr_ofdm[i+1] = (word & 0xff00) >> 8;
- }
-
- /* 3Read crystal calibration and thermal meter indication on 87SE. */
- eeprom_93cx6_read(&eeprom, EEPROM_RSV>>1, &tmpu16);
-
- /* Crystal calibration for Xin and Xout resp. */
- priv->XtalCal_Xout = tmpu16 & EEPROM_XTAL_CAL_XOUT_MASK;
- priv->XtalCal_Xin = (tmpu16 & EEPROM_XTAL_CAL_XIN_MASK) >> 4;
- if ((tmpu16 & EEPROM_XTAL_CAL_ENABLE) >> 12)
- priv->bXtalCalibration = true;
-
- /* Thermal meter reference indication. */
- priv->ThermalMeter = (u8)((tmpu16 & EEPROM_THERMAL_METER_MASK) >> 8);
- if ((tmpu16 & EEPROM_THERMAL_METER_ENABLE) >> 13)
- priv->bTxPowerTrack = true;
-
- priv->rf_sleep = rtl8225z4_rf_sleep;
- priv->rf_wakeup = rtl8225z4_rf_wakeup;
- DMESGW("**PLEASE** REPORT SUCCESSFUL/UNSUCCESSFUL TO Realtek!");
-
- priv->rf_close = rtl8225z2_rf_close;
- priv->rf_init = rtl8225z2_rf_init;
- priv->rf_set_chan = rtl8225z2_rf_set_chan;
- priv->rf_set_sens = NULL;
-
- if (0 != alloc_rx_desc_ring(dev, priv->rxbuffersize, priv->rxringcount))
- return -ENOMEM;
-
- if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txringcount,
- TX_MANAGEPRIORITY_RING_ADDR))
- return -ENOMEM;
-
- if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txringcount,
- TX_BKPRIORITY_RING_ADDR))
- return -ENOMEM;
-
- if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txringcount,
- TX_BEPRIORITY_RING_ADDR))
- return -ENOMEM;
-
- if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txringcount,
- TX_VIPRIORITY_RING_ADDR))
- return -ENOMEM;
-
- if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txringcount,
- TX_VOPRIORITY_RING_ADDR))
- return -ENOMEM;
-
- if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txringcount,
- TX_HIGHPRIORITY_RING_ADDR))
- return -ENOMEM;
-
- if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txbeaconcount,
- TX_BEACON_RING_ADDR))
- return -ENOMEM;
-
- if (request_irq(dev->irq, rtl8180_interrupt,
- IRQF_SHARED, dev->name, dev)) {
- DMESGE("Error allocating IRQ %d", dev->irq);
- return -1;
- } else {
- priv->irq = dev->irq;
- DMESG("IRQ %d", dev->irq);
- }
-
- return 0;
-}
-
-void rtl8180_no_hw_wep(struct net_device *dev)
-{
-}
-
-void rtl8180_set_hw_wep(struct net_device *dev)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- u8 pgreg;
- u8 security;
- u32 key0_word4;
-
- pgreg = read_nic_byte(dev, PGSELECT);
- write_nic_byte(dev, PGSELECT, pgreg & ~(1<<PGSELECT_PG_SHIFT));
-
- key0_word4 = read_nic_dword(dev, KEY0+4+4+4);
- key0_word4 &= ~0xff;
- key0_word4 |= priv->key0[3] & 0xff;
- write_nic_dword(dev, KEY0, (priv->key0[0]));
- write_nic_dword(dev, KEY0+4, (priv->key0[1]));
- write_nic_dword(dev, KEY0+4+4, (priv->key0[2]));
- write_nic_dword(dev, KEY0+4+4+4, (key0_word4));
-
- security = read_nic_byte(dev, SECURITY);
- security |= (1<<SECURITY_WEP_TX_ENABLE_SHIFT);
- security |= (1<<SECURITY_WEP_RX_ENABLE_SHIFT);
- security &= ~SECURITY_ENCRYP_MASK;
- security |= (SECURITY_ENCRYP_104<<SECURITY_ENCRYP_SHIFT);
-
- write_nic_byte(dev, SECURITY, security);
-
- DMESG("key %x %x %x %x", read_nic_dword(dev, KEY0+4+4+4),
- read_nic_dword(dev, KEY0+4+4), read_nic_dword(dev, KEY0+4),
- read_nic_dword(dev, KEY0));
-}
-
-
-void rtl8185_rf_pins_enable(struct net_device *dev)
-{
- write_nic_word(dev, RFPinsEnable, 0x1fff); /* | tmp); */
-}
-
-void rtl8185_set_anaparam2(struct net_device *dev, u32 a)
-{
- u8 conf3;
-
- rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
-
- conf3 = read_nic_byte(dev, CONFIG3);
- write_nic_byte(dev, CONFIG3, conf3 | (1<<CONFIG3_ANAPARAM_W_SHIFT));
- write_nic_dword(dev, ANAPARAM2, a);
-
- conf3 = read_nic_byte(dev, CONFIG3);
- write_nic_byte(dev, CONFIG3, conf3 & ~(1<<CONFIG3_ANAPARAM_W_SHIFT));
- rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
-}
-
-void rtl8180_set_anaparam(struct net_device *dev, u32 a)
-{
- u8 conf3;
-
- rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
-
- conf3 = read_nic_byte(dev, CONFIG3);
- write_nic_byte(dev, CONFIG3, conf3 | (1<<CONFIG3_ANAPARAM_W_SHIFT));
- write_nic_dword(dev, ANAPARAM, a);
-
- conf3 = read_nic_byte(dev, CONFIG3);
- write_nic_byte(dev, CONFIG3, conf3 & ~(1<<CONFIG3_ANAPARAM_W_SHIFT));
- rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
-}
-
-void rtl8185_tx_antenna(struct net_device *dev, u8 ant)
-{
- write_nic_byte(dev, TX_ANTENNA, ant);
- force_pci_posting(dev);
- mdelay(1);
-}
-
-static void rtl8185_write_phy(struct net_device *dev, u8 adr, u32 data)
-{
- u32 phyw;
-
- adr |= 0x80;
-
- phyw = ((data<<8) | adr);
-
- /* Note: we must write 0xff7c after 0x7d-0x7f to write BB register. */
- write_nic_byte(dev, 0x7f, ((phyw & 0xff000000) >> 24));
- write_nic_byte(dev, 0x7e, ((phyw & 0x00ff0000) >> 16));
- write_nic_byte(dev, 0x7d, ((phyw & 0x0000ff00) >> 8));
- write_nic_byte(dev, 0x7c, ((phyw & 0x000000ff)));
-}
-
-inline void write_phy_ofdm(struct net_device *dev, u8 adr, u32 data)
-{
- data = data & 0xff;
- rtl8185_write_phy(dev, adr, data);
-}
-
-void write_phy_cck(struct net_device *dev, u8 adr, u32 data)
-{
- data = data & 0xff;
- rtl8185_write_phy(dev, adr, data | 0x10000);
-}
-
-/*
- * This configures registers for beacon tx and enables it via
- * rtl8180_beacon_tx_enable(). rtl8180_beacon_tx_disable() might
- * be used to stop beacon transmission
- */
-void rtl8180_start_tx_beacon(struct net_device *dev)
-{
- u16 word;
-
- DMESG("Enabling beacon TX");
- rtl8180_prepare_beacon(dev);
- rtl8180_irq_disable(dev);
- rtl8180_beacon_tx_enable(dev);
-
- word = read_nic_word(dev, AtimWnd) & ~AtimWnd_AtimWnd;
- write_nic_word(dev, AtimWnd, word); /* word |= */
-
- word = read_nic_word(dev, BintrItv);
- word &= ~BintrItv_BintrItv;
- word |= 1000; /* priv->ieee80211->current_network.beacon_interval *
- * ((priv->txbeaconcount > 1)?(priv->txbeaconcount-1):1);
- * FIXME: check if correct ^^ worked with 0x3e8;
- */
- write_nic_word(dev, BintrItv, word);
-
- rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
-
- rtl8185b_irq_enable(dev);
-}
-
-static struct net_device_stats *rtl8180_stats(struct net_device *dev)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
-
- return &priv->ieee80211->stats;
-}
-
-/*
- * Change current and default preamble mode.
- */
-static bool MgntActSet_802_11_PowerSaveMode(struct r8180_priv *priv,
- enum rt_ps_mode rtPsMode)
-{
- /* Currently, we do not change power save mode on IBSS mode. */
- if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
- return false;
-
- priv->ieee80211->ps = rtPsMode;
-
- return true;
-}
-
-static void LeisurePSEnter(struct r8180_priv *priv)
-{
- if (priv->bLeisurePs)
- if (priv->ieee80211->ps == IEEE80211_PS_DISABLED)
- /* IEEE80211_PS_ENABLE */
- MgntActSet_802_11_PowerSaveMode(priv,
- IEEE80211_PS_MBCAST | IEEE80211_PS_UNICAST);
-}
-
-static void LeisurePSLeave(struct r8180_priv *priv)
-{
- if (priv->bLeisurePs)
- if (priv->ieee80211->ps != IEEE80211_PS_DISABLED)
- MgntActSet_802_11_PowerSaveMode(
- priv, IEEE80211_PS_DISABLED);
-}
-
-void rtl8180_hw_wakeup_wq(struct work_struct *work)
-{
- struct delayed_work *dwork = to_delayed_work(work);
- struct ieee80211_device *ieee = container_of(
- dwork, struct ieee80211_device, hw_wakeup_wq);
- struct net_device *dev = ieee->dev;
-
- rtl8180_hw_wakeup(dev);
-}
-
-void rtl8180_hw_sleep_wq(struct work_struct *work)
-{
- struct delayed_work *dwork = to_delayed_work(work);
- struct ieee80211_device *ieee = container_of(
- dwork, struct ieee80211_device, hw_sleep_wq);
- struct net_device *dev = ieee->dev;
-
- rtl8180_hw_sleep_down(dev);
-}
-
-static void MgntLinkKeepAlive(struct r8180_priv *priv)
-{
- if (priv->keepAliveLevel == 0)
- return;
-
- if (priv->ieee80211->state == IEEE80211_LINKED) {
- /*
- * Keep-Alive.
- */
-
- if ((priv->keepAliveLevel == 2) ||
- (priv->link_detect.last_num_tx_unicast ==
- priv->NumTxUnicast &&
- priv->link_detect.last_num_rx_unicast ==
- priv->ieee80211->NumRxUnicast)
- ) {
- priv->link_detect.idle_count++;
-
- /*
- * Send a Keep-Alive packet packet to AP if we had
- * been idle for a while.
- */
- if (priv->link_detect.idle_count >=
- KEEP_ALIVE_INTERVAL /
- CHECK_FOR_HANG_PERIOD - 1) {
- priv->link_detect.idle_count = 0;
- ieee80211_sta_ps_send_null_frame(
- priv->ieee80211, false);
- }
- } else {
- priv->link_detect.idle_count = 0;
- }
- priv->link_detect.last_num_tx_unicast = priv->NumTxUnicast;
- priv->link_detect.last_num_rx_unicast =
- priv->ieee80211->NumRxUnicast;
- }
-}
-
-void rtl8180_watch_dog(struct net_device *dev)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- bool bEnterPS = false;
- bool bBusyTraffic = false;
- u32 TotalRxNum = 0;
- u16 SlotIndex = 0;
- u16 i = 0;
- if (priv->ieee80211->actscanning == false) {
- if ((priv->ieee80211->iw_mode != IW_MODE_ADHOC) &&
- (priv->ieee80211->state == IEEE80211_NOLINK) &&
- (priv->ieee80211->beinretry == false) &&
- (priv->eRFPowerState == RF_ON))
- IPSEnter(dev);
- }
- if ((priv->ieee80211->state == IEEE80211_LINKED) &&
- (priv->ieee80211->iw_mode == IW_MODE_INFRA)) {
- SlotIndex = (priv->link_detect.slot_index++) %
- priv->link_detect.slot_num;
-
- priv->link_detect.rx_frame_num[SlotIndex] =
- priv->ieee80211->NumRxDataInPeriod +
- priv->ieee80211->NumRxBcnInPeriod;
-
- for (i = 0; i < priv->link_detect.slot_num; i++)
- TotalRxNum += priv->link_detect.rx_frame_num[i];
-
- if (TotalRxNum == 0) {
- priv->ieee80211->state = IEEE80211_ASSOCIATING;
- queue_work(priv->ieee80211->wq,
- &priv->ieee80211->associate_procedure_wq);
- }
- }
-
- MgntLinkKeepAlive(priv);
-
- LeisurePSLeave(priv);
-
- if (priv->ieee80211->state == IEEE80211_LINKED) {
- priv->link_detect.num_rx_ok_in_period =
- priv->ieee80211->NumRxDataInPeriod;
- if (priv->link_detect.num_rx_ok_in_period > 666 ||
- priv->link_detect.num_tx_ok_in_period > 666) {
- bBusyTraffic = true;
- }
- if ((priv->link_detect.num_rx_ok_in_period +
- priv->link_detect.num_tx_ok_in_period > 8)
- || (priv->link_detect.num_rx_ok_in_period > 2)) {
- bEnterPS = false;
- } else
- bEnterPS = true;
-
- if (bEnterPS)
- LeisurePSEnter(priv);
- else
- LeisurePSLeave(priv);
- } else
- LeisurePSLeave(priv);
- priv->link_detect.b_busy_traffic = bBusyTraffic;
- priv->link_detect.num_rx_ok_in_period = 0;
- priv->link_detect.num_tx_ok_in_period = 0;
- priv->ieee80211->NumRxDataInPeriod = 0;
- priv->ieee80211->NumRxBcnInPeriod = 0;
-}
-
-static int _rtl8180_up(struct net_device *dev)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
-
- priv->up = 1;
-
- DMESG("Bringing up iface");
- rtl8185b_adapter_start(dev);
- rtl8185b_rx_enable(dev);
- rtl8185b_tx_enable(dev);
- if (priv->bInactivePs) {
- if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
- IPSLeave(dev);
- }
- timer_rate_adaptive((unsigned long)dev);
- watch_dog_adaptive((unsigned long)dev);
- if (priv->bSwAntennaDiverity)
- SwAntennaDiversityTimerCallback(dev);
- ieee80211_softmac_start_protocol(priv->ieee80211);
- return 0;
-}
-
-static int rtl8180_open(struct net_device *dev)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- int ret;
-
- down(&priv->wx_sem);
- ret = rtl8180_up(dev);
- up(&priv->wx_sem);
- return ret;
-}
-
-int rtl8180_up(struct net_device *dev)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
-
- if (priv->up == 1)
- return -1;
-
- return _rtl8180_up(dev);
-}
-
-static int rtl8180_close(struct net_device *dev)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- int ret;
-
- down(&priv->wx_sem);
- ret = rtl8180_down(dev);
- up(&priv->wx_sem);
-
- return ret;
-}
-
-int rtl8180_down(struct net_device *dev)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
-
- if (priv->up == 0)
- return -1;
-
- priv->up = 0;
-
- ieee80211_softmac_stop_protocol(priv->ieee80211);
- /* FIXME */
- if (!netif_queue_stopped(dev))
- netif_stop_queue(dev);
- rtl8180_rtx_disable(dev);
- rtl8180_irq_disable(dev);
- del_timer_sync(&priv->watch_dog_timer);
- del_timer_sync(&priv->rateadapter_timer);
- cancel_delayed_work(&priv->ieee80211->rate_adapter_wq);
- cancel_delayed_work(&priv->ieee80211->hw_wakeup_wq);
- cancel_delayed_work(&priv->ieee80211->hw_sleep_wq);
- cancel_delayed_work(&priv->ieee80211->hw_dig_wq);
- cancel_delayed_work(&priv->ieee80211->tx_pw_wq);
- del_timer_sync(&priv->SwAntennaDiversityTimer);
- SetZebraRFPowerState8185(dev, RF_OFF);
- memset(&priv->ieee80211->current_network,
- 0, sizeof(struct ieee80211_network));
- priv->ieee80211->state = IEEE80211_NOLINK;
- return 0;
-}
-
-void rtl8180_restart_wq(struct work_struct *work)
-{
- struct r8180_priv *priv = container_of(
- work, struct r8180_priv, reset_wq);
- struct net_device *dev = priv->dev;
-
- down(&priv->wx_sem);
-
- rtl8180_commit(dev);
-
- up(&priv->wx_sem);
-}
-
-static void rtl8180_restart(struct net_device *dev)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
-
- schedule_work(&priv->reset_wq);
-}
-
-void rtl8180_commit(struct net_device *dev)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
-
- if (priv->up == 0)
- return;
-
- del_timer_sync(&priv->watch_dog_timer);
- del_timer_sync(&priv->rateadapter_timer);
- cancel_delayed_work(&priv->ieee80211->rate_adapter_wq);
- cancel_delayed_work(&priv->ieee80211->hw_wakeup_wq);
- cancel_delayed_work(&priv->ieee80211->hw_sleep_wq);
- cancel_delayed_work(&priv->ieee80211->hw_dig_wq);
- cancel_delayed_work(&priv->ieee80211->tx_pw_wq);
- del_timer_sync(&priv->SwAntennaDiversityTimer);
- ieee80211_softmac_stop_protocol(priv->ieee80211);
- rtl8180_irq_disable(dev);
- rtl8180_rtx_disable(dev);
- _rtl8180_up(dev);
-}
-
-static void r8180_set_multicast(struct net_device *dev)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- short promisc;
-
- promisc = (dev->flags & IFF_PROMISC) ? 1 : 0;
-
- if (promisc != priv->promisc)
- rtl8180_restart(dev);
-
- priv->promisc = promisc;
-}
-
-static int r8180_set_mac_adr(struct net_device *dev, void *mac)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- struct sockaddr *addr = mac;
-
- down(&priv->wx_sem);
-
- memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
-
- if (priv->ieee80211->iw_mode == IW_MODE_MASTER)
- memcpy(priv->ieee80211->current_network.bssid,
- dev->dev_addr, ETH_ALEN);
-
- if (priv->up) {
- rtl8180_down(dev);
- rtl8180_up(dev);
- }
-
- up(&priv->wx_sem);
-
- return 0;
-}
-
-/* based on ipw2200 driver */
-static int rtl8180_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- struct iwreq *wrq = (struct iwreq *) rq;
- int ret = -1;
-
- switch (cmd) {
- case RTL_IOCTL_WPA_SUPPLICANT:
- ret = ieee80211_wpa_supplicant_ioctl(
- priv->ieee80211, &wrq->u.data);
- return ret;
- default:
- return -EOPNOTSUPP;
- }
-
- return -EOPNOTSUPP;
-}
-
-static const struct net_device_ops rtl8180_netdev_ops = {
- .ndo_open = rtl8180_open,
- .ndo_stop = rtl8180_close,
- .ndo_get_stats = rtl8180_stats,
- .ndo_tx_timeout = rtl8180_restart,
- .ndo_do_ioctl = rtl8180_ioctl,
- .ndo_set_rx_mode = r8180_set_multicast,
- .ndo_set_mac_address = r8180_set_mac_adr,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
- .ndo_start_xmit = ieee80211_rtl_xmit,
-};
-
-static int rtl8180_pci_probe(struct pci_dev *pdev,
- const struct pci_device_id *id)
-{
- unsigned long ioaddr = 0;
- struct net_device *dev = NULL;
- struct r8180_priv *priv = NULL;
- u8 unit = 0;
- int ret = -ENODEV;
-
- unsigned long pmem_start, pmem_len, pmem_flags;
-
- DMESG("Configuring chip resources");
-
- if (pci_enable_device(pdev)) {
- DMESG("Failed to enable PCI device");
- return -EIO;
- }
-
- pci_set_master(pdev);
- pci_set_dma_mask(pdev, 0xffffff00ULL);
- pci_set_consistent_dma_mask(pdev, 0xffffff00ULL);
- dev = alloc_ieee80211(sizeof(struct r8180_priv));
- if (!dev) {
- ret = -ENOMEM;
- goto fail_free;
- }
- priv = ieee80211_priv(dev);
- priv->ieee80211 = netdev_priv(dev);
-
- pci_set_drvdata(pdev, dev);
- SET_NETDEV_DEV(dev, &pdev->dev);
-
- priv = ieee80211_priv(dev);
- priv->pdev = pdev;
-
- pmem_start = pci_resource_start(pdev, 1);
- pmem_len = pci_resource_len(pdev, 1);
- pmem_flags = pci_resource_flags(pdev, 1);
-
- if (!(pmem_flags & IORESOURCE_MEM)) {
- DMESG("region #1 not a MMIO resource, aborting");
- goto fail;
- }
-
- if (!request_mem_region(pmem_start, pmem_len, RTL8180_MODULE_NAME)) {
- DMESG("request_mem_region failed!");
- goto fail;
- }
-
- ioaddr = (unsigned long)ioremap_nocache(pmem_start, pmem_len);
- if (ioaddr == (unsigned long)NULL) {
- DMESG("ioremap failed!");
- goto fail1;
- }
-
- dev->mem_start = ioaddr; /* shared mem start */
- dev->mem_end = ioaddr + pci_resource_len(pdev, 0); /* shared mem end */
-
- pci_read_config_byte(pdev, 0x05, &unit);
- pci_write_config_byte(pdev, 0x05, unit & (~0x04));
-
- dev->irq = pdev->irq;
- priv->irq = 0;
-
- dev->netdev_ops = &rtl8180_netdev_ops;
- dev->wireless_handlers = &r8180_wx_handlers_def;
-
- dev->type = ARPHRD_ETHER;
- dev->watchdog_timeo = HZ*3;
-
- if (dev_alloc_name(dev, ifname) < 0) {
- DMESG("Oops: devname already taken! Trying wlan%%d...\n");
- strcpy(ifname, "wlan%d");
- dev_alloc_name(dev, ifname);
- }
-
- if (rtl8180_init(dev) != 0) {
- DMESG("Initialization failed");
- goto fail1;
- }
-
- netif_carrier_off(dev);
-
- if (register_netdev(dev))
- goto fail1;
-
- rtl8180_proc_init_one(dev);
-
- DMESG("Driver probe completed\n");
- return 0;
-fail1:
- if (dev->mem_start != (unsigned long)NULL) {
- iounmap((void __iomem *)dev->mem_start);
- release_mem_region(pci_resource_start(pdev, 1),
- pci_resource_len(pdev, 1));
- }
-fail:
- if (dev) {
- if (priv->irq) {
- free_irq(dev->irq, dev);
- dev->irq = 0;
- }
- free_ieee80211(dev);
- }
-
-fail_free:
- pci_disable_device(pdev);
-
- DMESG("wlan driver load failed\n");
- return ret;
-}
-
-static void rtl8180_pci_remove(struct pci_dev *pdev)
-{
- struct r8180_priv *priv;
- struct net_device *dev = pci_get_drvdata(pdev);
-
- if (dev) {
- unregister_netdev(dev);
-
- priv = ieee80211_priv(dev);
-
- rtl8180_proc_remove_one(dev);
- rtl8180_down(dev);
- priv->rf_close(dev);
- rtl8180_reset(dev);
- mdelay(10);
-
- if (priv->irq) {
- DMESG("Freeing irq %d", dev->irq);
- free_irq(dev->irq, dev);
- priv->irq = 0;
- }
-
- free_rx_desc_ring(dev);
- free_tx_desc_rings(dev);
-
- if (dev->mem_start != (unsigned long)NULL) {
- iounmap((void __iomem *)dev->mem_start);
- release_mem_region(pci_resource_start(pdev, 1),
- pci_resource_len(pdev, 1));
- }
-
- free_ieee80211(dev);
- }
- pci_disable_device(pdev);
-
- DMESG("wlan driver removed\n");
-}
-
-static int __init rtl8180_pci_module_init(void)
-{
- int ret;
-
- ret = ieee80211_crypto_init();
- if (ret) {
- pr_err("ieee80211_crypto_init() failed %d\n", ret);
- return ret;
- }
- ret = ieee80211_crypto_tkip_init();
- if (ret) {
- pr_err("ieee80211_crypto_tkip_init() failed %d\n", ret);
- return ret;
- }
- ret = ieee80211_crypto_ccmp_init();
- if (ret) {
- pr_err("ieee80211_crypto_ccmp_init() failed %d\n", ret);
- return ret;
- }
- ret = ieee80211_crypto_wep_init();
- if (ret) {
- pr_err("ieee80211_crypto_wep_init() failed %d\n", ret);
- return ret;
- }
-
- pr_info("\nLinux kernel driver for RTL8180 / RTL8185 based WLAN cards\n");
- pr_info("Copyright (c) 2004-2005, Andrea Merello\n");
- DMESG("Initializing module");
- DMESG("Wireless extensions version %d", WIRELESS_EXT);
- rtl8180_proc_module_init();
-
- if (pci_register_driver(&rtl8180_pci_driver)) {
- DMESG("No device found");
- return -ENODEV;
- }
- return 0;
-}
-
-static void __exit rtl8180_pci_module_exit(void)
-{
- pci_unregister_driver(&rtl8180_pci_driver);
- rtl8180_proc_module_remove();
- ieee80211_crypto_tkip_exit();
- ieee80211_crypto_ccmp_exit();
- ieee80211_crypto_wep_exit();
- ieee80211_crypto_deinit();
- DMESG("Exiting");
-}
-
-static void rtl8180_try_wake_queue(struct net_device *dev, int pri)
-{
- unsigned long flags;
- short enough_desc;
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
- spin_lock_irqsave(&priv->tx_lock, flags);
- enough_desc = check_nic_enought_desc(dev, pri);
- spin_unlock_irqrestore(&priv->tx_lock, flags);
-
- if (enough_desc)
- ieee80211_rtl_wake_queue(priv->ieee80211);
-}
-
-static void rtl8180_tx_isr(struct net_device *dev, int pri, short error)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- u32 *tail; /* tail virtual addr */
- u32 *head; /* head virtual addr */
- u32 *begin; /* start of ring virtual addr */
- u32 *nicv; /* nic pointer virtual addr */
- u32 nic; /* nic pointer physical addr */
- u32 nicbegin; /* start of ring physical addr */
- unsigned long flag;
- /* physical addr are ok on 32 bits since we set DMA mask */
- int offs;
- int j, i;
- int hd;
- if (error)
- priv->stats.txretry++;
- spin_lock_irqsave(&priv->tx_lock, flag);
- switch (pri) {
- case MANAGE_PRIORITY:
- tail = priv->txmapringtail;
- begin = priv->txmapring;
- head = priv->txmapringhead;
- nic = read_nic_dword(dev, TX_MANAGEPRIORITY_RING_ADDR);
- nicbegin = priv->txmapringdma;
- break;
- case BK_PRIORITY:
- tail = priv->txbkpringtail;
- begin = priv->txbkpring;
- head = priv->txbkpringhead;
- nic = read_nic_dword(dev, TX_BKPRIORITY_RING_ADDR);
- nicbegin = priv->txbkpringdma;
- break;
- case BE_PRIORITY:
- tail = priv->txbepringtail;
- begin = priv->txbepring;
- head = priv->txbepringhead;
- nic = read_nic_dword(dev, TX_BEPRIORITY_RING_ADDR);
- nicbegin = priv->txbepringdma;
- break;
- case VI_PRIORITY:
- tail = priv->txvipringtail;
- begin = priv->txvipring;
- head = priv->txvipringhead;
- nic = read_nic_dword(dev, TX_VIPRIORITY_RING_ADDR);
- nicbegin = priv->txvipringdma;
- break;
- case VO_PRIORITY:
- tail = priv->txvopringtail;
- begin = priv->txvopring;
- head = priv->txvopringhead;
- nic = read_nic_dword(dev, TX_VOPRIORITY_RING_ADDR);
- nicbegin = priv->txvopringdma;
- break;
- case HI_PRIORITY:
- tail = priv->txhpringtail;
- begin = priv->txhpring;
- head = priv->txhpringhead;
- nic = read_nic_dword(dev, TX_HIGHPRIORITY_RING_ADDR);
- nicbegin = priv->txhpringdma;
- break;
-
- default:
- spin_unlock_irqrestore(&priv->tx_lock, flag);
- return;
- }
-
- nicv = (u32 *)((nic - nicbegin) + (u8 *)begin);
- if ((head <= tail && (nicv > tail || nicv < head)) ||
- (head > tail && (nicv > tail && nicv < head))) {
- DMESGW("nic has lost pointer");
- spin_unlock_irqrestore(&priv->tx_lock, flag);
- rtl8180_restart(dev);
- return;
- }
-
- /*
- * We check all the descriptors between the head and the nic,
- * but not the currently pointed by the nic (the next to be txed)
- * and the previous of the pointed (might be in process ??)
- */
- offs = (nic - nicbegin);
- offs = offs / 8 / 4;
- hd = (head - begin) / 8;
-
- if (offs >= hd)
- j = offs - hd;
- else
- j = offs + (priv->txringcount-1-hd);
-
- j -= 2;
- if (j < 0)
- j = 0;
-
- for (i = 0; i < j; i++) {
- if ((*head) & (1<<31))
- break;
- if (((*head)&(0x10000000)) != 0) {
- priv->CurrRetryCnt += (u16)((*head) & (0x000000ff));
- if (!error)
- priv->NumTxOkTotal++;
- }
-
- if (!error)
- priv->NumTxOkBytesTotal += (*(head+3)) & (0x00000fff);
-
- *head = *head & ~(1<<31);
-
- if ((head - begin)/8 == priv->txringcount-1)
- head = begin;
- else
- head += 8;
- }
-
- /*
- * The head has been moved to the last certainly TXed
- * (or at least processed by the nic) packet.
- * The driver take forcefully owning of all these packets
- * If the packet previous of the nic pointer has been
- * processed this doesn't matter: it will be checked
- * here at the next round. Anyway if no more packet are
- * TXed no memory leak occur at all.
- */
-
- switch (pri) {
- case MANAGE_PRIORITY:
- priv->txmapringhead = head;
-
- if (priv->ack_tx_to_ieee) {
- if (rtl8180_is_tx_queue_empty(dev)) {
- priv->ack_tx_to_ieee = 0;
- ieee80211_ps_tx_ack(priv->ieee80211, !error);
- }
- }
- break;
- case BK_PRIORITY:
- priv->txbkpringhead = head;
- break;
- case BE_PRIORITY:
- priv->txbepringhead = head;
- break;
- case VI_PRIORITY:
- priv->txvipringhead = head;
- break;
- case VO_PRIORITY:
- priv->txvopringhead = head;
- break;
- case HI_PRIORITY:
- priv->txhpringhead = head;
- break;
- }
-
- spin_unlock_irqrestore(&priv->tx_lock, flag);
-}
-
-static irqreturn_t rtl8180_interrupt(int irq, void *netdev)
-{
- struct net_device *dev = (struct net_device *) netdev;
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- unsigned long flags;
- u32 inta;
-
- /* We should return IRQ_NONE, but for now let me keep this */
- if (priv->irq_enabled == 0)
- return IRQ_HANDLED;
-
- spin_lock_irqsave(&priv->irq_th_lock, flags);
-
- /* ISR: 4bytes */
- inta = read_nic_dword(dev, ISR);
- write_nic_dword(dev, ISR, inta); /* reset int situation */
-
- priv->stats.shints++;
-
- if (!inta) {
- spin_unlock_irqrestore(&priv->irq_th_lock, flags);
- return IRQ_HANDLED;
- /*
- * most probably we can safely return IRQ_NONE,
- * but for now is better to avoid problems
- */
- }
-
- if (inta == 0xffff) {
- /* HW disappeared */
- spin_unlock_irqrestore(&priv->irq_th_lock, flags);
- return IRQ_HANDLED;
- }
-
- priv->stats.ints++;
-
- if (!netif_running(dev)) {
- spin_unlock_irqrestore(&priv->irq_th_lock, flags);
- return IRQ_HANDLED;
- }
-
- if (inta & ISR_TimeOut)
- write_nic_dword(dev, TimerInt, 0);
-
- if (inta & ISR_TBDOK)
- priv->stats.txbeacon++;
-
- if (inta & ISR_TBDER)
- priv->stats.txbeaconerr++;
-
- if (inta & IMR_TMGDOK)
- rtl8180_tx_isr(dev, MANAGE_PRIORITY, 0);
-
- if (inta & ISR_THPDER) {
- priv->stats.txhperr++;
- rtl8180_tx_isr(dev, HI_PRIORITY, 1);
- priv->ieee80211->stats.tx_errors++;
- }
-
- if (inta & ISR_THPDOK) { /* High priority tx ok */
- priv->link_detect.num_tx_ok_in_period++;
- priv->stats.txhpokint++;
- rtl8180_tx_isr(dev, HI_PRIORITY, 0);
- }
-
- if (inta & ISR_RER)
- priv->stats.rxerr++;
-
- if (inta & ISR_TBKDER) { /* corresponding to BK_PRIORITY */
- priv->stats.txbkperr++;
- priv->ieee80211->stats.tx_errors++;
- rtl8180_tx_isr(dev, BK_PRIORITY, 1);
- rtl8180_try_wake_queue(dev, BK_PRIORITY);
- }
-
- if (inta & ISR_TBEDER) { /* corresponding to BE_PRIORITY */
- priv->stats.txbeperr++;
- priv->ieee80211->stats.tx_errors++;
- rtl8180_tx_isr(dev, BE_PRIORITY, 1);
- rtl8180_try_wake_queue(dev, BE_PRIORITY);
- }
- if (inta & ISR_TNPDER) { /* corresponding to VO_PRIORITY */
- priv->stats.txnperr++;
- priv->ieee80211->stats.tx_errors++;
- rtl8180_tx_isr(dev, NORM_PRIORITY, 1);
- rtl8180_try_wake_queue(dev, NORM_PRIORITY);
- }
-
- if (inta & ISR_TLPDER) { /* corresponding to VI_PRIORITY */
- priv->stats.txlperr++;
- priv->ieee80211->stats.tx_errors++;
- rtl8180_tx_isr(dev, LOW_PRIORITY, 1);
- rtl8180_try_wake_queue(dev, LOW_PRIORITY);
- }
-
- if (inta & ISR_ROK) {
- priv->stats.rxint++;
- tasklet_schedule(&priv->irq_rx_tasklet);
- }
-
- if (inta & ISR_RQoSOK) {
- priv->stats.rxint++;
- tasklet_schedule(&priv->irq_rx_tasklet);
- }
-
- if (inta & ISR_BcnInt)
- rtl8180_prepare_beacon(dev);
-
- if (inta & ISR_RDU) {
- DMESGW("No RX descriptor available");
- priv->stats.rxrdu++;
- tasklet_schedule(&priv->irq_rx_tasklet);
- }
-
- if (inta & ISR_RXFOVW) {
- priv->stats.rxoverflow++;
- tasklet_schedule(&priv->irq_rx_tasklet);
- }
-
- if (inta & ISR_TXFOVW)
- priv->stats.txoverflow++;
-
- if (inta & ISR_TNPDOK) { /* Normal priority tx ok */
- priv->link_detect.num_tx_ok_in_period++;
- priv->stats.txnpokint++;
- rtl8180_tx_isr(dev, NORM_PRIORITY, 0);
- rtl8180_try_wake_queue(dev, NORM_PRIORITY);
- }
-
- if (inta & ISR_TLPDOK) { /* Low priority tx ok */
- priv->link_detect.num_tx_ok_in_period++;
- priv->stats.txlpokint++;
- rtl8180_tx_isr(dev, LOW_PRIORITY, 0);
- rtl8180_try_wake_queue(dev, LOW_PRIORITY);
- }
-
- if (inta & ISR_TBKDOK) { /* corresponding to BK_PRIORITY */
- priv->stats.txbkpokint++;
- priv->link_detect.num_tx_ok_in_period++;
- rtl8180_tx_isr(dev, BK_PRIORITY, 0);
- rtl8180_try_wake_queue(dev, BE_PRIORITY);
- }
-
- if (inta & ISR_TBEDOK) { /* corresponding to BE_PRIORITY */
- priv->stats.txbeperr++;
- priv->link_detect.num_tx_ok_in_period++;
- rtl8180_tx_isr(dev, BE_PRIORITY, 0);
- rtl8180_try_wake_queue(dev, BE_PRIORITY);
- }
- force_pci_posting(dev);
- spin_unlock_irqrestore(&priv->irq_th_lock, flags);
-
- return IRQ_HANDLED;
-}
-
-void rtl8180_irq_rx_tasklet(struct r8180_priv *priv)
-{
- rtl8180_rx(priv->dev);
-}
-
-void GPIOChangeRFWorkItemCallBack(struct work_struct *work)
-{
- struct ieee80211_device *ieee = container_of(
- work, struct ieee80211_device, GPIOChangeRFWorkItem.work);
- struct net_device *dev = ieee->dev;
- struct r8180_priv *priv = ieee80211_priv(dev);
- u8 btPSR;
- u8 btConfig0;
- enum rt_rf_power_state eRfPowerStateToSet;
- bool bActuallySet = false;
-
- char *argv[3];
- static char *RadioPowerPath = "/etc/acpi/events/RadioPower.sh";
- static char *envp[] = {"HOME=/", "TERM=linux",
- "PATH=/usr/bin:/bin", NULL};
- static int readf_count;
-
- readf_count = (readf_count+1)%0xffff;
- /* We should turn off LED before polling FF51[4]. */
-
- /* Turn off LED. */
- btPSR = read_nic_byte(dev, PSR);
- write_nic_byte(dev, PSR, (btPSR & ~BIT3));
-
- /* It need to delay 4us suggested */
- udelay(4);
-
- /* HW radio On/Off according to the value of FF51[4](config0) */
- btConfig0 = btPSR = read_nic_byte(dev, CONFIG0);
-
- eRfPowerStateToSet = (btConfig0 & BIT4) ? RF_ON : RF_OFF;
-
- /* Turn LED back on when radio enabled */
- if (eRfPowerStateToSet == RF_ON)
- write_nic_byte(dev, PSR, btPSR | BIT3);
-
- if ((priv->ieee80211->bHwRadioOff == true) &&
- (eRfPowerStateToSet == RF_ON)) {
- priv->ieee80211->bHwRadioOff = false;
- bActuallySet = true;
- } else if ((priv->ieee80211->bHwRadioOff == false) &&
- (eRfPowerStateToSet == RF_OFF)) {
- priv->ieee80211->bHwRadioOff = true;
- bActuallySet = true;
- }
-
- if (bActuallySet) {
- MgntActSet_RF_State(dev, eRfPowerStateToSet, RF_CHANGE_BY_HW);
-
- /* To update the UI status for Power status changed */
- if (priv->ieee80211->bHwRadioOff == true)
- argv[1] = "RFOFF";
- else
- argv[1] = "RFON";
- argv[0] = RadioPowerPath;
- argv[2] = NULL;
-
- call_usermodehelper(RadioPowerPath, argv, envp, UMH_WAIT_PROC);
- }
-}
-
-module_init(rtl8180_pci_module_init);
-module_exit(rtl8180_pci_module_exit);
diff --git a/drivers/staging/rtl8187se/r8180_dm.c b/drivers/staging/rtl8187se/r8180_dm.c
deleted file mode 100644
index 8c020e064869..000000000000
--- a/drivers/staging/rtl8187se/r8180_dm.c
+++ /dev/null
@@ -1,1139 +0,0 @@
-#include "r8180_dm.h"
-#include "r8180_hw.h"
-#include "r8180_93cx6.h"
-
- /* Return TRUE if we shall perform High Power Mechanism, FALSE otherwise. */
-#define RATE_ADAPTIVE_TIMER_PERIOD 300
-
-bool CheckHighPower(struct net_device *dev)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- struct ieee80211_device *ieee = priv->ieee80211;
-
- if (!priv->bRegHighPowerMechanism)
- return false;
-
- if (ieee->state == IEEE80211_LINKED_SCANNING)
- return false;
-
- return true;
-}
-
-/*
- * Description:
- * Update Tx power level if necessary.
- * See also DoRxHighPower() and SetTxPowerLevel8185() for reference.
- *
- * Note:
- * The reason why we udpate Tx power level here instead of DoRxHighPower()
- * is the number of IO to change Tx power is much more than channel TR switch
- * and they are related to OFDM and MAC registers.
- * So, we don't want to update it so frequently in per-Rx packet base.
- */
-static void DoTxHighPower(struct net_device *dev)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- u16 HiPwrUpperTh = 0;
- u16 HiPwrLowerTh = 0;
- u8 RSSIHiPwrUpperTh;
- u8 RSSIHiPwrLowerTh;
- u8 u1bTmp;
- char OfdmTxPwrIdx, CckTxPwrIdx;
-
- HiPwrUpperTh = priv->RegHiPwrUpperTh;
- HiPwrLowerTh = priv->RegHiPwrLowerTh;
-
- HiPwrUpperTh = HiPwrUpperTh * 10;
- HiPwrLowerTh = HiPwrLowerTh * 10;
- RSSIHiPwrUpperTh = priv->RegRSSIHiPwrUpperTh;
- RSSIHiPwrLowerTh = priv->RegRSSIHiPwrLowerTh;
-
- /* lzm add 080826 */
- OfdmTxPwrIdx = priv->chtxpwr_ofdm[priv->ieee80211->current_network.channel];
- CckTxPwrIdx = priv->chtxpwr[priv->ieee80211->current_network.channel];
-
- if ((priv->UndecoratedSmoothedSS > HiPwrUpperTh) ||
- (priv->bCurCCKPkt && (priv->CurCCKRSSI > RSSIHiPwrUpperTh))) {
- /* Stevenl suggested that degrade 8dbm in high power sate. 2007-12-04 Isaiah */
-
- priv->bToUpdateTxPwr = true;
- u1bTmp = read_nic_byte(dev, CCK_TXAGC);
-
- /* If it never enter High Power. */
- if (CckTxPwrIdx == u1bTmp) {
- u1bTmp = (u1bTmp > 16) ? (u1bTmp - 16) : 0; /* 8dbm */
- write_nic_byte(dev, CCK_TXAGC, u1bTmp);
-
- u1bTmp = read_nic_byte(dev, OFDM_TXAGC);
- u1bTmp = (u1bTmp > 16) ? (u1bTmp - 16) : 0; /* 8dbm */
- write_nic_byte(dev, OFDM_TXAGC, u1bTmp);
- }
-
- } else if ((priv->UndecoratedSmoothedSS < HiPwrLowerTh) &&
- (!priv->bCurCCKPkt || priv->CurCCKRSSI < RSSIHiPwrLowerTh)) {
- if (priv->bToUpdateTxPwr) {
- priv->bToUpdateTxPwr = false;
- /* SD3 required. */
- u1bTmp = read_nic_byte(dev, CCK_TXAGC);
- if (u1bTmp < CckTxPwrIdx) {
- write_nic_byte(dev, CCK_TXAGC, CckTxPwrIdx);
- }
-
- u1bTmp = read_nic_byte(dev, OFDM_TXAGC);
- if (u1bTmp < OfdmTxPwrIdx) {
- write_nic_byte(dev, OFDM_TXAGC, OfdmTxPwrIdx);
- }
- }
- }
-}
-
-
-/*
- * Description:
- * Callback function of UpdateTxPowerWorkItem.
- * Because of some event happened, e.g. CCX TPC, High Power Mechanism,
- * We update Tx power of current channel again.
- */
-void rtl8180_tx_pw_wq(struct work_struct *work)
-{
- struct delayed_work *dwork = to_delayed_work(work);
- struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, tx_pw_wq);
- struct net_device *dev = ieee->dev;
-
- DoTxHighPower(dev);
-}
-
-
-/*
- * Return TRUE if we shall perform DIG Mechanism, FALSE otherwise.
- */
-bool CheckDig(struct net_device *dev)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- struct ieee80211_device *ieee = priv->ieee80211;
-
- if (!priv->bDigMechanism)
- return false;
-
- if (ieee->state != IEEE80211_LINKED)
- return false;
-
- if ((priv->ieee80211->rate / 5) < 36) /* Schedule Dig under all OFDM rates. By Bruce, 2007-06-01. */
- return false;
- return true;
-}
-/*
- * Implementation of DIG for Zebra and Zebra2.
- */
-static void DIG_Zebra(struct net_device *dev)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- u16 CCKFalseAlarm, OFDMFalseAlarm;
- u16 OfdmFA1, OfdmFA2;
- int InitialGainStep = 7; /* The number of initial gain stages. */
- int LowestGainStage = 4; /* The capable lowest stage of performing dig workitem. */
- u32 AwakePeriodIn2Sec = 0;
-
- CCKFalseAlarm = (u16)(priv->FalseAlarmRegValue & 0x0000ffff);
- OFDMFalseAlarm = (u16)((priv->FalseAlarmRegValue >> 16) & 0x0000ffff);
- OfdmFA1 = 0x15;
- OfdmFA2 = ((u16)(priv->RegDigOfdmFaUpTh)) << 8;
-
- /* The number of initial gain steps is different, by Bruce, 2007-04-13. */
- if (priv->InitialGain == 0) { /* autoDIG */
- /* Advised from SD3 DZ */
- priv->InitialGain = 4; /* In 87B, m74dBm means State 4 (m82dBm) */
- }
- /* Advised from SD3 DZ */
- OfdmFA1 = 0x20;
-
-#if 1 /* lzm reserved 080826 */
- AwakePeriodIn2Sec = (2000 - priv->DozePeriodInPast2Sec);
- priv->DozePeriodInPast2Sec = 0;
-
- if (AwakePeriodIn2Sec) {
- OfdmFA1 = (u16)((OfdmFA1 * AwakePeriodIn2Sec) / 2000);
- OfdmFA2 = (u16)((OfdmFA2 * AwakePeriodIn2Sec) / 2000);
- } else {
- ;
- }
-#endif
-
- InitialGainStep = 8;
- LowestGainStage = priv->RegBModeGainStage; /* Lowest gain stage. */
-
- if (OFDMFalseAlarm > OfdmFA1) {
- if (OFDMFalseAlarm > OfdmFA2) {
- priv->DIG_NumberFallbackVote++;
- if (priv->DIG_NumberFallbackVote > 1) {
- /* serious OFDM False Alarm, need fallback */
- if (priv->InitialGain < InitialGainStep) {
- priv->InitialGainBackUp = priv->InitialGain;
-
- priv->InitialGain = (priv->InitialGain + 1);
- UpdateInitialGain(dev);
- }
- priv->DIG_NumberFallbackVote = 0;
- priv->DIG_NumberUpgradeVote = 0;
- }
- } else {
- if (priv->DIG_NumberFallbackVote)
- priv->DIG_NumberFallbackVote--;
- }
- priv->DIG_NumberUpgradeVote = 0;
- } else {
- if (priv->DIG_NumberFallbackVote)
- priv->DIG_NumberFallbackVote--;
- priv->DIG_NumberUpgradeVote++;
-
- if (priv->DIG_NumberUpgradeVote > 9) {
- if (priv->InitialGain > LowestGainStage) { /* In 87B, m78dBm means State 4 (m864dBm) */
- priv->InitialGainBackUp = priv->InitialGain;
-
- priv->InitialGain = (priv->InitialGain - 1);
- UpdateInitialGain(dev);
- }
- priv->DIG_NumberFallbackVote = 0;
- priv->DIG_NumberUpgradeVote = 0;
- }
- }
-}
-
-/*
- * Dispatch DIG implementation according to RF.
- */
-static void DynamicInitGain(struct net_device *dev)
-{
- DIG_Zebra(dev);
-}
-
-void rtl8180_hw_dig_wq(struct work_struct *work)
-{
- struct delayed_work *dwork = to_delayed_work(work);
- struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, hw_dig_wq);
- struct net_device *dev = ieee->dev;
- struct r8180_priv *priv = ieee80211_priv(dev);
-
- /* Read CCK and OFDM False Alarm. */
- priv->FalseAlarmRegValue = read_nic_dword(dev, CCK_FALSE_ALARM);
-
-
- /* Adjust Initial Gain dynamically. */
- DynamicInitGain(dev);
-
-}
-
-static int IncludedInSupportedRates(struct r8180_priv *priv, u8 TxRate)
-{
- u8 rate_len;
- u8 rate_ex_len;
- u8 RateMask = 0x7F;
- u8 idx;
- unsigned short Found = 0;
- u8 NaiveTxRate = TxRate&RateMask;
-
- rate_len = priv->ieee80211->current_network.rates_len;
- rate_ex_len = priv->ieee80211->current_network.rates_ex_len;
- for (idx = 0; idx < rate_len; idx++) {
- if ((priv->ieee80211->current_network.rates[idx] & RateMask) == NaiveTxRate) {
- Found = 1;
- goto found_rate;
- }
- }
- for (idx = 0; idx < rate_ex_len; idx++) {
- if ((priv->ieee80211->current_network.rates_ex[idx] & RateMask) == NaiveTxRate) {
- Found = 1;
- goto found_rate;
- }
- }
- return Found;
-found_rate:
- return Found;
-}
-
-/*
- * Get the Tx rate one degree up form the input rate in the supported rates.
- * Return the upgrade rate if it is successed, otherwise return the input rate.
- */
-static u8 GetUpgradeTxRate(struct net_device *dev, u8 rate)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- u8 UpRate;
-
- /* Upgrade 1 degree. */
- switch (rate) {
- case 108: /* Up to 54Mbps. */
- UpRate = 108;
- break;
-
- case 96: /* Up to 54Mbps. */
- UpRate = 108;
- break;
-
- case 72: /* Up to 48Mbps. */
- UpRate = 96;
- break;
-
- case 48: /* Up to 36Mbps. */
- UpRate = 72;
- break;
-
- case 36: /* Up to 24Mbps. */
- UpRate = 48;
- break;
-
- case 22: /* Up to 18Mbps. */
- UpRate = 36;
- break;
-
- case 11: /* Up to 11Mbps. */
- UpRate = 22;
- break;
-
- case 4: /* Up to 5.5Mbps. */
- UpRate = 11;
- break;
-
- case 2: /* Up to 2Mbps. */
- UpRate = 4;
- break;
-
- default:
- printk("GetUpgradeTxRate(): Input Tx Rate(%d) is undefined!\n", rate);
- return rate;
- }
- /* Check if the rate is valid. */
- if (IncludedInSupportedRates(priv, UpRate)) {
- return UpRate;
- } else {
- return rate;
- }
- return rate;
-}
-/*
- * Get the Tx rate one degree down form the input rate in the supported rates.
- * Return the degrade rate if it is successed, otherwise return the input rate.
- */
-
-static u8 GetDegradeTxRate(struct net_device *dev, u8 rate)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- u8 DownRate;
-
- /* Upgrade 1 degree. */
- switch (rate) {
- case 108: /* Down to 48Mbps. */
- DownRate = 96;
- break;
-
- case 96: /* Down to 36Mbps. */
- DownRate = 72;
- break;
-
- case 72: /* Down to 24Mbps. */
- DownRate = 48;
- break;
-
- case 48: /* Down to 18Mbps. */
- DownRate = 36;
- break;
-
- case 36: /* Down to 11Mbps. */
- DownRate = 22;
- break;
-
- case 22: /* Down to 5.5Mbps. */
- DownRate = 11;
- break;
-
- case 11: /* Down to 2Mbps. */
- DownRate = 4;
- break;
-
- case 4: /* Down to 1Mbps. */
- DownRate = 2;
- break;
-
- case 2: /* Down to 1Mbps. */
- DownRate = 2;
- break;
-
- default:
- printk("GetDegradeTxRate(): Input Tx Rate(%d) is undefined!\n", rate);
- return rate;
- }
- /* Check if the rate is valid. */
- if (IncludedInSupportedRates(priv, DownRate)) {
- return DownRate;
- } else {
- return rate;
- }
- return rate;
-}
-/*
- * Helper function to determine if specified data rate is
- * CCK rate.
- */
-
-static bool MgntIsCckRate(u16 rate)
-{
- bool bReturn = false;
-
- if ((rate <= 22) && (rate != 12) && (rate != 18)) {
- bReturn = true;
- }
-
- return bReturn;
-}
-/*
- * Description:
- * Tx Power tracking mechanism routine on 87SE.
- */
-void TxPwrTracking87SE(struct net_device *dev)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- u8 tmpu1Byte, CurrentThermal, Idx;
- char CckTxPwrIdx, OfdmTxPwrIdx;
-
- tmpu1Byte = read_nic_byte(dev, EN_LPF_CAL);
- CurrentThermal = (tmpu1Byte & 0xf0) >> 4; /*[ 7:4]: thermal meter indication. */
- CurrentThermal = (CurrentThermal > 0x0c) ? 0x0c : CurrentThermal;/* lzm add 080826 */
-
- if (CurrentThermal != priv->ThermalMeter) {
- /* Update Tx Power level on each channel. */
- for (Idx = 1; Idx < 15; Idx++) {
- CckTxPwrIdx = priv->chtxpwr[Idx];
- OfdmTxPwrIdx = priv->chtxpwr_ofdm[Idx];
-
- if (CurrentThermal > priv->ThermalMeter) {
- /* higher thermal meter. */
- CckTxPwrIdx += (CurrentThermal - priv->ThermalMeter) * 2;
- OfdmTxPwrIdx += (CurrentThermal - priv->ThermalMeter) * 2;
-
- if (CckTxPwrIdx > 35)
- CckTxPwrIdx = 35; /* Force TxPower to maximal index. */
- if (OfdmTxPwrIdx > 35)
- OfdmTxPwrIdx = 35;
- } else {
- /* lower thermal meter. */
- CckTxPwrIdx -= (priv->ThermalMeter - CurrentThermal) * 2;
- OfdmTxPwrIdx -= (priv->ThermalMeter - CurrentThermal) * 2;
-
- if (CckTxPwrIdx < 0)
- CckTxPwrIdx = 0;
- if (OfdmTxPwrIdx < 0)
- OfdmTxPwrIdx = 0;
- }
-
- /* Update TxPower level on CCK and OFDM resp. */
- priv->chtxpwr[Idx] = CckTxPwrIdx;
- priv->chtxpwr_ofdm[Idx] = OfdmTxPwrIdx;
- }
-
- /* Update TxPower level immediately. */
- rtl8225z2_SetTXPowerLevel(dev, priv->ieee80211->current_network.channel);
- }
- priv->ThermalMeter = CurrentThermal;
-}
-static void StaRateAdaptive87SE(struct net_device *dev)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- unsigned long CurrTxokCnt;
- u16 CurrRetryCnt;
- u16 CurrRetryRate;
- unsigned long CurrRxokCnt;
- bool bTryUp = false;
- bool bTryDown = false;
- u8 TryUpTh = 1;
- u8 TryDownTh = 2;
- u32 TxThroughput;
- long CurrSignalStrength;
- bool bUpdateInitialGain = false;
- u8 u1bOfdm = 0, u1bCck = 0;
- char OfdmTxPwrIdx, CckTxPwrIdx;
-
- priv->RateAdaptivePeriod = RATE_ADAPTIVE_TIMER_PERIOD;
-
-
- CurrRetryCnt = priv->CurrRetryCnt;
- CurrTxokCnt = priv->NumTxOkTotal - priv->LastTxokCnt;
- CurrRxokCnt = priv->ieee80211->NumRxOkTotal - priv->LastRxokCnt;
- CurrSignalStrength = priv->Stats_RecvSignalPower;
- TxThroughput = (u32)(priv->NumTxOkBytesTotal - priv->LastTxOKBytes);
- priv->LastTxOKBytes = priv->NumTxOkBytesTotal;
- priv->CurrentOperaRate = priv->ieee80211->rate / 5;
- /* 2 Compute retry ratio. */
- if (CurrTxokCnt > 0) {
- CurrRetryRate = (u16)(CurrRetryCnt * 100 / CurrTxokCnt);
- } else {
- /* It may be serious retry. To distinguish serious retry or no packets modified by Bruce */
- CurrRetryRate = (u16)(CurrRetryCnt * 100 / 1);
- }
-
- priv->LastRetryCnt = priv->CurrRetryCnt;
- priv->LastTxokCnt = priv->NumTxOkTotal;
- priv->LastRxokCnt = priv->ieee80211->NumRxOkTotal;
- priv->CurrRetryCnt = 0;
-
- /* 2No Tx packets, return to init_rate or not? */
- if (CurrRetryRate == 0 && CurrTxokCnt == 0) {
- /*
- * After 9 (30*300ms) seconds in this condition, we try to raise rate.
- */
- priv->TryupingCountNoData++;
-
- /* [TRC Dell Lab] Extend raised period from 4.5sec to 9sec, Isaiah 2008-02-15 18:00 */
- if (priv->TryupingCountNoData > 30) {
- priv->TryupingCountNoData = 0;
- priv->CurrentOperaRate = GetUpgradeTxRate(dev, priv->CurrentOperaRate);
- /* Reset Fail Record */
- priv->LastFailTxRate = 0;
- priv->LastFailTxRateSS = -200;
- priv->FailTxRateCount = 0;
- }
- goto SetInitialGain;
- } else {
- priv->TryupingCountNoData = 0; /*Reset trying up times. */
- }
-
-
- /*
- * For Netgear case, I comment out the following signal strength estimation,
- * which can results in lower rate to transmit when sample is NOT enough (e.g. PING request).
- *
- * Restructure rate adaptive as the following main stages:
- * (1) Add retry threshold in 54M upgrading condition with signal strength.
- * (2) Add the mechanism to degrade to CCK rate according to signal strength
- * and retry rate.
- * (3) Remove all Initial Gain Updates over OFDM rate. To avoid the complicated
- * situation, Initial Gain Update is upon on DIG mechanism except CCK rate.
- * (4) Add the mechanism of trying to upgrade tx rate.
- * (5) Record the information of upping tx rate to avoid trying upping tx rate constantly.
- *
- */
-
- /*
- * 11Mbps or 36Mbps
- * Check more times in these rate(key rates).
- */
- if (priv->CurrentOperaRate == 22 || priv->CurrentOperaRate == 72)
- TryUpTh += 9;
- /*
- * Let these rates down more difficult.
- */
- if (MgntIsCckRate(priv->CurrentOperaRate) || priv->CurrentOperaRate == 36)
- TryDownTh += 1;
-
- /* 1 Adjust Rate. */
- if (priv->bTryuping == true) {
- /* 2 For Test Upgrading mechanism
- * Note:
- * Sometimes the throughput is upon on the capability between the AP and NIC,
- * thus the low data rate does not improve the performance.
- * We randomly upgrade the data rate and check if the retry rate is improved.
- */
-
- /* Upgrading rate did not improve the retry rate, fallback to the original rate. */
- if ((CurrRetryRate > 25) && TxThroughput < priv->LastTxThroughput) {
- /*Not necessary raising rate, fall back rate. */
- bTryDown = true;
- } else {
- priv->bTryuping = false;
- }
- } else if (CurrSignalStrength > -47 && (CurrRetryRate < 50)) {
- /*
- * 2For High Power
- *
- * Return to highest data rate, if signal strength is good enough.
- * SignalStrength threshold(-50dbm) is for RTL8186.
- * Revise SignalStrength threshold to -51dbm.
- */
- /* Also need to check retry rate for safety, by Bruce, 2007-06-05. */
- if (priv->CurrentOperaRate != priv->ieee80211->current_network.HighestOperaRate) {
- bTryUp = true;
- /* Upgrade Tx Rate directly. */
- priv->TryupingCount += TryUpTh;
- }
-
- } else if (CurrTxokCnt > 9 && CurrTxokCnt < 100 && CurrRetryRate >= 600) {
- /*
- *2 For Serious Retry
- *
- * Traffic is not busy but our Tx retry is serious.
- */
- bTryDown = true;
- /* Let Rate Mechanism to degrade tx rate directly. */
- priv->TryDownCountLowData += TryDownTh;
- } else if (priv->CurrentOperaRate == 108) {
- /* 2For 54Mbps */
- /* Air Link */
- if ((CurrRetryRate > 26) && (priv->LastRetryRate > 25)) {
- bTryDown = true;
- }
- /* Cable Link */
- else if ((CurrRetryRate > 17) && (priv->LastRetryRate > 16) && (CurrSignalStrength > -72)) {
- bTryDown = true;
- }
-
- if (bTryDown && (CurrSignalStrength < -75)) /* cable link */
- priv->TryDownCountLowData += TryDownTh;
- } else if (priv->CurrentOperaRate == 96) {
- /* 2For 48Mbps */
- /* Air Link */
- if (((CurrRetryRate > 48) && (priv->LastRetryRate > 47))) {
- bTryDown = true;
- } else if (((CurrRetryRate > 21) && (priv->LastRetryRate > 20)) && (CurrSignalStrength > -74)) { /* Cable Link */
- /* Down to rate 36Mbps. */
- bTryDown = true;
- } else if ((CurrRetryRate > (priv->LastRetryRate + 50)) && (priv->FailTxRateCount > 2)) {
- bTryDown = true;
- priv->TryDownCountLowData += TryDownTh;
- } else if ((CurrRetryRate < 8) && (priv->LastRetryRate < 8)) { /* TO DO: need to consider (RSSI) */
- bTryUp = true;
- }
-
- if (bTryDown && (CurrSignalStrength < -75)) {
- priv->TryDownCountLowData += TryDownTh;
- }
- } else if (priv->CurrentOperaRate == 72) {
- /* 2For 36Mbps */
- if ((CurrRetryRate > 43) && (priv->LastRetryRate > 41)) {
- /* Down to rate 24Mbps. */
- bTryDown = true;
- } else if ((CurrRetryRate > (priv->LastRetryRate + 50)) && (priv->FailTxRateCount > 2)) {
- bTryDown = true;
- priv->TryDownCountLowData += TryDownTh;
- } else if ((CurrRetryRate < 15) && (priv->LastRetryRate < 16)) { /* TO DO: need to consider (RSSI) */
- bTryUp = true;
- }
-
- if (bTryDown && (CurrSignalStrength < -80))
- priv->TryDownCountLowData += TryDownTh;
-
- } else if (priv->CurrentOperaRate == 48) {
- /* 2For 24Mbps */
- /* Air Link */
- if (((CurrRetryRate > 63) && (priv->LastRetryRate > 62))) {
- bTryDown = true;
- } else if (((CurrRetryRate > 33) && (priv->LastRetryRate > 32)) && (CurrSignalStrength > -82)) { /* Cable Link */
- bTryDown = true;
- } else if ((CurrRetryRate > (priv->LastRetryRate + 50)) && (priv->FailTxRateCount > 2)) {
- bTryDown = true;
- priv->TryDownCountLowData += TryDownTh;
- } else if ((CurrRetryRate < 20) && (priv->LastRetryRate < 21)) { /* TO DO: need to consider (RSSI) */
- bTryUp = true;
- }
-
- if (bTryDown && (CurrSignalStrength < -82))
- priv->TryDownCountLowData += TryDownTh;
-
- } else if (priv->CurrentOperaRate == 36) {
- if (((CurrRetryRate > 85) && (priv->LastRetryRate > 86))) {
- bTryDown = true;
- } else if ((CurrRetryRate > (priv->LastRetryRate + 50)) && (priv->FailTxRateCount > 2)) {
- bTryDown = true;
- priv->TryDownCountLowData += TryDownTh;
- } else if ((CurrRetryRate < 22) && (priv->LastRetryRate < 23)) { /* TO DO: need to consider (RSSI) */
- bTryUp = true;
- }
- } else if (priv->CurrentOperaRate == 22) {
- /* 2For 11Mbps */
- if (CurrRetryRate > 95) {
- bTryDown = true;
- } else if ((CurrRetryRate < 29) && (priv->LastRetryRate < 30)) { /*TO DO: need to consider (RSSI) */
- bTryUp = true;
- }
- } else if (priv->CurrentOperaRate == 11) {
- /* 2For 5.5Mbps */
- if (CurrRetryRate > 149) {
- bTryDown = true;
- } else if ((CurrRetryRate < 60) && (priv->LastRetryRate < 65)) {
- bTryUp = true;
- }
- } else if (priv->CurrentOperaRate == 4) {
- /* 2For 2 Mbps */
- if ((CurrRetryRate > 99) && (priv->LastRetryRate > 99)) {
- bTryDown = true;
- } else if ((CurrRetryRate < 65) && (priv->LastRetryRate < 70)) {
- bTryUp = true;
- }
- } else if (priv->CurrentOperaRate == 2) {
- /* 2For 1 Mbps */
- if ((CurrRetryRate < 70) && (priv->LastRetryRate < 75)) {
- bTryUp = true;
- }
- }
-
- if (bTryUp && bTryDown)
- printk("StaRateAdaptive87B(): Tx Rate tried upping and downing simultaneously!\n");
-
- /* 1 Test Upgrading Tx Rate
- * Sometimes the cause of the low throughput (high retry rate) is the compatibility between the AP and NIC.
- * To test if the upper rate may cause lower retry rate, this mechanism randomly occurs to test upgrading tx rate.
- */
- if (!bTryUp && !bTryDown && (priv->TryupingCount == 0) && (priv->TryDownCountLowData == 0)
- && priv->CurrentOperaRate != priv->ieee80211->current_network.HighestOperaRate && priv->FailTxRateCount < 2) {
- if (jiffies % (CurrRetryRate + 101) == 0) {
- bTryUp = true;
- priv->bTryuping = true;
- }
- }
-
- /* 1 Rate Mechanism */
- if (bTryUp) {
- priv->TryupingCount++;
- priv->TryDownCountLowData = 0;
-
- /*
- * Check more times if we need to upgrade indeed.
- * Because the largest value of pHalData->TryupingCount is 0xFFFF and
- * the largest value of pHalData->FailTxRateCount is 0x14,
- * this condition will be satisfied at most every 2 min.
- */
-
- if ((priv->TryupingCount > (TryUpTh + priv->FailTxRateCount * priv->FailTxRateCount)) ||
- (CurrSignalStrength > priv->LastFailTxRateSS) || priv->bTryuping) {
- priv->TryupingCount = 0;
- /*
- * When transferring from CCK to OFDM, DIG is an important issue.
- */
- if (priv->CurrentOperaRate == 22)
- bUpdateInitialGain = true;
-
- /*
- * The difference in throughput between 48Mbps and 36Mbps is 8M.
- * So, we must be careful in this rate scale. Isaiah 2008-02-15.
- */
- if (((priv->CurrentOperaRate == 72) || (priv->CurrentOperaRate == 48) || (priv->CurrentOperaRate == 36)) &&
- (priv->FailTxRateCount > 2))
- priv->RateAdaptivePeriod = (RATE_ADAPTIVE_TIMER_PERIOD / 2);
-
- /* (1)To avoid upgrade frequently to the fail tx rate, add the FailTxRateCount into the threshold. */
- /* (2)If the signal strength is increased, it may be able to upgrade. */
-
- priv->CurrentOperaRate = GetUpgradeTxRate(dev, priv->CurrentOperaRate);
-
- if (priv->CurrentOperaRate == 36) {
- priv->bUpdateARFR = true;
- write_nic_word(dev, ARFR, 0x0F8F); /* bypass 12/9/6 */
- } else if (priv->bUpdateARFR) {
- priv->bUpdateARFR = false;
- write_nic_word(dev, ARFR, 0x0FFF); /* set 1M ~ 54Mbps. */
- }
-
- /* Update Fail Tx rate and count. */
- if (priv->LastFailTxRate != priv->CurrentOperaRate) {
- priv->LastFailTxRate = priv->CurrentOperaRate;
- priv->FailTxRateCount = 0;
- priv->LastFailTxRateSS = -200; /* Set lowest power. */
- }
- }
- } else {
- if (priv->TryupingCount > 0)
- priv->TryupingCount--;
- }
-
- if (bTryDown) {
- priv->TryDownCountLowData++;
- priv->TryupingCount = 0;
-
- /* Check if Tx rate can be degraded or Test trying upgrading should fallback. */
- if (priv->TryDownCountLowData > TryDownTh || priv->bTryuping) {
- priv->TryDownCountLowData = 0;
- priv->bTryuping = false;
- /* Update fail information. */
- if (priv->LastFailTxRate == priv->CurrentOperaRate) {
- priv->FailTxRateCount++;
- /* Record the Tx fail rate signal strength. */
- if (CurrSignalStrength > priv->LastFailTxRateSS)
- priv->LastFailTxRateSS = CurrSignalStrength;
- } else {
- priv->LastFailTxRate = priv->CurrentOperaRate;
- priv->FailTxRateCount = 1;
- priv->LastFailTxRateSS = CurrSignalStrength;
- }
- priv->CurrentOperaRate = GetDegradeTxRate(dev, priv->CurrentOperaRate);
-
- /* Reduce chariot training time at weak signal strength situation. SD3 ED demand. */
- if ((CurrSignalStrength < -80) && (priv->CurrentOperaRate > 72)) {
- priv->CurrentOperaRate = 72;
- }
-
- if (priv->CurrentOperaRate == 36) {
- priv->bUpdateARFR = true;
- write_nic_word(dev, ARFR, 0x0F8F); /* bypass 12/9/6 */
- } else if (priv->bUpdateARFR) {
- priv->bUpdateARFR = false;
- write_nic_word(dev, ARFR, 0x0FFF); /* set 1M ~ 54Mbps. */
- }
-
- /*
- * When it is CCK rate, it may need to update initial gain to receive lower power packets.
- */
- if (MgntIsCckRate(priv->CurrentOperaRate)) {
- bUpdateInitialGain = true;
- }
- }
- } else {
- if (priv->TryDownCountLowData > 0)
- priv->TryDownCountLowData--;
- }
-
- /*
- * Keep the Tx fail rate count to equal to 0x15 at most.
- * Reduce the fail count at least to 10 sec if tx rate is tending stable.
- */
- if (priv->FailTxRateCount >= 0x15 ||
- (!bTryUp && !bTryDown && priv->TryDownCountLowData == 0 && priv->TryupingCount && priv->FailTxRateCount > 0x6)) {
- priv->FailTxRateCount--;
- }
-
-
- OfdmTxPwrIdx = priv->chtxpwr_ofdm[priv->ieee80211->current_network.channel];
- CckTxPwrIdx = priv->chtxpwr[priv->ieee80211->current_network.channel];
-
- /* Mac0x9e increase 2 level in 36M~18M situation */
- if ((priv->CurrentOperaRate < 96) && (priv->CurrentOperaRate > 22)) {
- u1bCck = read_nic_byte(dev, CCK_TXAGC);
- u1bOfdm = read_nic_byte(dev, OFDM_TXAGC);
-
- /* case 1: Never enter High power */
- if (u1bCck == CckTxPwrIdx) {
- if (u1bOfdm != (OfdmTxPwrIdx + 2)) {
- priv->bEnhanceTxPwr = true;
- u1bOfdm = ((u1bOfdm + 2) > 35) ? 35 : (u1bOfdm + 2);
- write_nic_byte(dev, OFDM_TXAGC, u1bOfdm);
- }
- } else if (u1bCck < CckTxPwrIdx) {
- /* case 2: enter high power */
- if (!priv->bEnhanceTxPwr) {
- priv->bEnhanceTxPwr = true;
- u1bOfdm = ((u1bOfdm + 2) > 35) ? 35 : (u1bOfdm + 2);
- write_nic_byte(dev, OFDM_TXAGC, u1bOfdm);
- }
- }
- } else if (priv->bEnhanceTxPwr) { /* 54/48/11/5.5/2/1 */
- u1bCck = read_nic_byte(dev, CCK_TXAGC);
- u1bOfdm = read_nic_byte(dev, OFDM_TXAGC);
-
- /* case 1: Never enter High power */
- if (u1bCck == CckTxPwrIdx) {
- priv->bEnhanceTxPwr = false;
- write_nic_byte(dev, OFDM_TXAGC, OfdmTxPwrIdx);
- }
- /* case 2: enter high power */
- else if (u1bCck < CckTxPwrIdx) {
- priv->bEnhanceTxPwr = false;
- u1bOfdm = ((u1bOfdm - 2) > 0) ? (u1bOfdm - 2) : 0;
- write_nic_byte(dev, OFDM_TXAGC, u1bOfdm);
- }
- }
-
- /*
- * We need update initial gain when we set tx rate "from OFDM to CCK" or
- * "from CCK to OFDM".
- */
-SetInitialGain:
- if (bUpdateInitialGain) {
- if (MgntIsCckRate(priv->CurrentOperaRate)) { /* CCK */
- if (priv->InitialGain > priv->RegBModeGainStage) {
- priv->InitialGainBackUp = priv->InitialGain;
-
- if (CurrSignalStrength < -85) /* Low power, OFDM [0x17] = 26. */
- /* SD3 SYs suggest that CurrSignalStrength < -65, ofdm 0x17=26. */
- priv->InitialGain = priv->RegBModeGainStage;
-
- else if (priv->InitialGain > priv->RegBModeGainStage + 1)
- priv->InitialGain -= 2;
-
- else
- priv->InitialGain--;
-
- printk("StaRateAdaptive87SE(): update init_gain to index %d for date rate %d\n", priv->InitialGain, priv->CurrentOperaRate);
- UpdateInitialGain(dev);
- }
- } else { /* OFDM */
- if (priv->InitialGain < 4) {
- priv->InitialGainBackUp = priv->InitialGain;
-
- priv->InitialGain++;
- printk("StaRateAdaptive87SE(): update init_gain to index %d for date rate %d\n", priv->InitialGain, priv->CurrentOperaRate);
- UpdateInitialGain(dev);
- }
- }
- }
-
- /* Record the related info */
- priv->LastRetryRate = CurrRetryRate;
- priv->LastTxThroughput = TxThroughput;
- priv->ieee80211->rate = priv->CurrentOperaRate * 5;
-}
-
-void rtl8180_rate_adapter(struct work_struct *work)
-{
- struct delayed_work *dwork = to_delayed_work(work);
- struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, rate_adapter_wq);
- struct net_device *dev = ieee->dev;
- StaRateAdaptive87SE(dev);
-}
-void timer_rate_adaptive(unsigned long data)
-{
- struct r8180_priv *priv = ieee80211_priv((struct net_device *)data);
- if (!priv->up) {
- return;
- }
- if ((priv->ieee80211->iw_mode != IW_MODE_MASTER)
- && (priv->ieee80211->state == IEEE80211_LINKED) &&
- (priv->ForcedDataRate == 0)) {
- queue_work(priv->ieee80211->wq, (void *)&priv->ieee80211->rate_adapter_wq);
- }
- priv->rateadapter_timer.expires = jiffies + MSECS(priv->RateAdaptivePeriod);
- add_timer(&priv->rateadapter_timer);
-}
-
-void SwAntennaDiversityRxOk8185(struct net_device *dev, u8 SignalStrength)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
- priv->AdRxOkCnt++;
-
- if (priv->AdRxSignalStrength != -1) {
- priv->AdRxSignalStrength = ((priv->AdRxSignalStrength * 7) + (SignalStrength * 3)) / 10;
- } else { /* Initialization case. */
- priv->AdRxSignalStrength = SignalStrength;
- }
-
- if (priv->LastRxPktAntenna) /* Main antenna. */
- priv->AdMainAntennaRxOkCnt++;
- else /* Aux antenna. */
- priv->AdAuxAntennaRxOkCnt++;
-}
- /* Change Antenna Switch. */
-bool SetAntenna8185(struct net_device *dev, u8 u1bAntennaIndex)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- bool bAntennaSwitched = false;
-
- switch (u1bAntennaIndex) {
- case 0:
- /* Mac register, main antenna */
- write_nic_byte(dev, ANTSEL, 0x03);
- /* base band */
- write_phy_cck(dev, 0x11, 0x9b); /* Config CCK RX antenna. */
- write_phy_ofdm(dev, 0x0d, 0x5c); /* Config OFDM RX antenna. */
-
- bAntennaSwitched = true;
- break;
-
- case 1:
- /* Mac register, aux antenna */
- write_nic_byte(dev, ANTSEL, 0x00);
- /* base band */
- write_phy_cck(dev, 0x11, 0xbb); /* Config CCK RX antenna. */
- write_phy_ofdm(dev, 0x0d, 0x54); /* Config OFDM RX antenna. */
-
- bAntennaSwitched = true;
-
- break;
-
- default:
- printk("SetAntenna8185: unknown u1bAntennaIndex(%d)\n", u1bAntennaIndex);
- break;
- }
-
- if (bAntennaSwitched)
- priv->CurrAntennaIndex = u1bAntennaIndex;
-
- return bAntennaSwitched;
-}
- /* Toggle Antenna switch. */
-bool SwitchAntenna(struct net_device *dev)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
- bool bResult;
-
- if (priv->CurrAntennaIndex == 0) {
- bResult = SetAntenna8185(dev, 1);
- } else {
- bResult = SetAntenna8185(dev, 0);
- }
-
- return bResult;
-}
-/*
- * Engine of SW Antenna Diversity mechanism.
- * Since 8187 has no Tx part information,
- * this implementation is only dependend on Rx part information.
- */
-void SwAntennaDiversity(struct net_device *dev)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- bool bSwCheckSS = false;
- if (bSwCheckSS) {
- priv->AdTickCount++;
-
- printk("(1) AdTickCount: %d, AdCheckPeriod: %d\n",
- priv->AdTickCount, priv->AdCheckPeriod);
- printk("(2) AdRxSignalStrength: %ld, AdRxSsThreshold: %ld\n",
- priv->AdRxSignalStrength, priv->AdRxSsThreshold);
- }
-
- /* Case 1. No Link. */
- if (priv->ieee80211->state != IEEE80211_LINKED) {
- priv->bAdSwitchedChecking = false;
- /* I switch antenna here to prevent any one of antenna is broken before link established, 2006.04.18, by rcnjko.. */
- SwitchAntenna(dev);
-
- /* Case 2. Linked but no packet receive.d */
- } else if (priv->AdRxOkCnt == 0) {
- priv->bAdSwitchedChecking = false;
- SwitchAntenna(dev);
-
- /* Case 3. Evaluate last antenna switch action and undo it if necessary. */
- } else if (priv->bAdSwitchedChecking == true) {
- priv->bAdSwitchedChecking = false;
-
- /* Adjust Rx signal strength threshold. */
- priv->AdRxSsThreshold = (priv->AdRxSignalStrength + priv->AdRxSsBeforeSwitched) / 2;
-
- priv->AdRxSsThreshold = (priv->AdRxSsThreshold > priv->AdMaxRxSsThreshold) ?
- priv->AdMaxRxSsThreshold : priv->AdRxSsThreshold;
- if (priv->AdRxSignalStrength < priv->AdRxSsBeforeSwitched) {
- /* Rx signal strength is not improved after we swtiched antenna. => Swich back. */
- /* Increase Antenna Diversity checking period due to bad decision. */
- priv->AdCheckPeriod *= 2;
- /* Increase Antenna Diversity checking period. */
- if (priv->AdCheckPeriod > priv->AdMaxCheckPeriod)
- priv->AdCheckPeriod = priv->AdMaxCheckPeriod;
-
- /* Wrong decision => switch back. */
- SwitchAntenna(dev);
- } else {
- /* Rx Signal Strength is improved. */
-
- /* Reset Antenna Diversity checking period to its min value. */
- priv->AdCheckPeriod = priv->AdMinCheckPeriod;
- }
-
- }
- /* Case 4. Evaluate if we shall switch antenna now. */
- /* Cause Table Speed is very fast in TRC Dell Lab, we check it every time. */
- else {
- priv->AdTickCount = 0;
-
- /*
- * <Roger_Notes> We evaluate RxOk counts for each antenna first and than
- * evaluate signal strength.
- * The following operation can overcome the disability of CCA on both two antennas
- * When signal strength was extremely low or high.
- * 2008.01.30.
- */
-
- /*
- * Evaluate RxOk count from each antenna if we shall switch default antenna now.
- */
- if ((priv->AdMainAntennaRxOkCnt < priv->AdAuxAntennaRxOkCnt)
- && (priv->CurrAntennaIndex == 0)) {
- /* We set Main antenna as default but RxOk count was less than Aux ones. */
-
- /* Switch to Aux antenna. */
- SwitchAntenna(dev);
- priv->bHWAdSwitched = true;
- } else if ((priv->AdAuxAntennaRxOkCnt < priv->AdMainAntennaRxOkCnt)
- && (priv->CurrAntennaIndex == 1)) {
- /* We set Aux antenna as default but RxOk count was less than Main ones. */
-
- /* Switch to Main antenna. */
- SwitchAntenna(dev);
- priv->bHWAdSwitched = true;
- } else {
- /* Default antenna is better. */
-
- /* Still need to check current signal strength. */
- priv->bHWAdSwitched = false;
- }
- /*
- * <Roger_Notes> We evaluate Rx signal strength ONLY when default antenna
- * didn't change by HW evaluation.
- * 2008.02.27.
- *
- * [TRC Dell Lab] SignalStrength is inaccuracy. Isaiah 2008-03-05
- * For example, Throughput of aux is better than main antenna(about 10M v.s 2M),
- * but AdRxSignalStrength is less than main.
- * Our guess is that main antenna have lower throughput and get many change
- * to receive more CCK packets(ex.Beacon) which have stronger SignalStrength.
- */
- if ((!priv->bHWAdSwitched) && (bSwCheckSS)) {
- /* Evaluate Rx signal strength if we shall switch antenna now. */
- if (priv->AdRxSignalStrength < priv->AdRxSsThreshold) {
- /* Rx signal strength is weak => Switch Antenna. */
- priv->AdRxSsBeforeSwitched = priv->AdRxSignalStrength;
- priv->bAdSwitchedChecking = true;
-
- SwitchAntenna(dev);
- } else {
- /* Rx signal strength is OK. */
- priv->bAdSwitchedChecking = false;
- /* Increase Rx signal strength threshold if necessary. */
- if ((priv->AdRxSignalStrength > (priv->AdRxSsThreshold + 10)) && /* Signal is much stronger than current threshold */
- priv->AdRxSsThreshold <= priv->AdMaxRxSsThreshold) { /* Current threhold is not yet reach upper limit. */
-
- priv->AdRxSsThreshold = (priv->AdRxSsThreshold + priv->AdRxSignalStrength) / 2;
- priv->AdRxSsThreshold = (priv->AdRxSsThreshold > priv->AdMaxRxSsThreshold) ?
- priv->AdMaxRxSsThreshold : priv->AdRxSsThreshold;/* +by amy 080312 */
- }
-
- /* Reduce Antenna Diversity checking period if possible. */
- if (priv->AdCheckPeriod > priv->AdMinCheckPeriod)
- priv->AdCheckPeriod /= 2;
- }
- }
- }
- /* Reset antenna diversity Rx related statistics. */
- priv->AdRxOkCnt = 0;
- priv->AdMainAntennaRxOkCnt = 0;
- priv->AdAuxAntennaRxOkCnt = 0;
-}
-
- /* Return TRUE if we shall perform Tx Power Tracking Mechanism, FALSE otherwise. */
-bool CheckTxPwrTracking(struct net_device *dev)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
- if (!priv->bTxPowerTrack)
- return false;
-
- /* if 87SE is in High Power , don't do Tx Power Tracking. asked by SD3 ED. 2008-08-08 Isaiah */
- if (priv->bToUpdateTxPwr)
- return false;
-
- return true;
-}
-
-
- /* Timer callback function of SW Antenna Diversity. */
-void SwAntennaDiversityTimerCallback(struct net_device *dev)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- enum rt_rf_power_state rtState;
-
- /* We do NOT need to switch antenna while RF is off. */
- rtState = priv->eRFPowerState;
- do {
- if (rtState == RF_OFF) {
- break;
- } else if (rtState == RF_SLEEP) {
- /* Don't access BB/RF under Disable PLL situation. */
- break;
- }
- SwAntennaDiversity(dev);
-
- } while (false);
-
- if (priv->up) {
- priv->SwAntennaDiversityTimer.expires = jiffies + MSECS(ANTENNA_DIVERSITY_TIMER_PERIOD);
- add_timer(&priv->SwAntennaDiversityTimer);
- }
-}
-
diff --git a/drivers/staging/rtl8187se/r8180_dm.h b/drivers/staging/rtl8187se/r8180_dm.h
deleted file mode 100644
index cb4046f346ef..000000000000
--- a/drivers/staging/rtl8187se/r8180_dm.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef R8180_DM_H
-#define R8180_DM_H
-
-#include "r8180.h"
-/* #include "r8180_hw.h" */
-/* #include "r8180_93cx6.h" */
-void SwAntennaDiversityRxOk8185(struct net_device *dev, u8 SignalStrength);
-bool SetAntenna8185(struct net_device *dev, u8 u1bAntennaIndex);
-bool SwitchAntenna(struct net_device *dev);
-void SwAntennaDiversity(struct net_device *dev);
-void SwAntennaDiversityTimerCallback(struct net_device *dev);
-bool CheckDig(struct net_device *dev);
-bool CheckHighPower(struct net_device *dev);
-void rtl8180_hw_dig_wq(struct work_struct *work);
-void rtl8180_tx_pw_wq(struct work_struct *work);
-void rtl8180_rate_adapter(struct work_struct *work);
-void TxPwrTracking87SE(struct net_device *dev);
-bool CheckTxPwrTracking(struct net_device *dev);
-void rtl8180_rate_adapter(struct work_struct *work);
-void timer_rate_adaptive(unsigned long data);
-
-
-#endif
diff --git a/drivers/staging/rtl8187se/r8180_hw.h b/drivers/staging/rtl8187se/r8180_hw.h
deleted file mode 100644
index e59d74f8ecfc..000000000000
--- a/drivers/staging/rtl8187se/r8180_hw.h
+++ /dev/null
@@ -1,588 +0,0 @@
-/*
- This is part of rtl8180 OpenSource driver.
- Copyright (C) Andrea Merello 2004-2005 <andrea.merello@gmail.com>
- Released under the terms of GPL (General Public Licence)
-
- Parts of this driver are based on the GPL part of the
- official Realtek driver.
- Parts of this driver are based on the rtl8180 driver skeleton
- from Patric Schenke & Andres Salomon.
- Parts of this driver are based on the Intel Pro Wireless
- 2100 GPL driver.
-
- We want to tanks the Authors of those projects
- and the Ndiswrapper project Authors.
-*/
-
-/* Mariusz Matuszek added full registers definition with Realtek's name */
-
-/* this file contains register definitions for the rtl8180 MAC controller */
-#ifndef R8180_HW
-#define R8180_HW
-
-
-#define BIT0 0x00000001
-#define BIT1 0x00000002
-#define BIT2 0x00000004
-#define BIT3 0x00000008
-#define BIT4 0x00000010
-#define BIT5 0x00000020
-#define BIT6 0x00000040
-#define BIT7 0x00000080
-#define BIT9 0x00000200
-#define BIT11 0x00000800
-#define BIT13 0x00002000
-#define BIT15 0x00008000
-#define BIT20 0x00100000
-#define BIT21 0x00200000
-#define BIT22 0x00400000
-#define BIT23 0x00800000
-#define BIT24 0x01000000
-#define BIT25 0x02000000
-#define BIT26 0x04000000
-#define BIT27 0x08000000
-#define BIT28 0x10000000
-#define BIT29 0x20000000
-#define BIT30 0x40000000
-#define BIT31 0x80000000
-
-#define MAX_SLEEP_TIME (10000)
-#define MIN_SLEEP_TIME (50)
-
-#define BB_HOST_BANG_EN (1<<2)
-#define BB_HOST_BANG_CLK (1<<1)
-
-#define MAC0 0
-#define MAC4 4
-
-#define CMD 0x37
-#define CMD_RST_SHIFT 4
-#define CMD_RX_ENABLE_SHIFT 3
-#define CMD_TX_ENABLE_SHIFT 2
-
-#define EPROM_CMD 0x50
-#define EPROM_CMD_RESERVED_MASK ((1<<5)|(1<<4))
-#define EPROM_CMD_OPERATING_MODE_SHIFT 6
-#define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6))
-#define EPROM_CMD_CONFIG 0x3
-#define EPROM_CMD_NORMAL 0
-#define EPROM_CMD_LOAD 1
-#define EPROM_CMD_PROGRAM 2
-#define EPROM_CS_SHIFT 3
-#define EPROM_CK_SHIFT 2
-#define EPROM_W_SHIFT 1
-#define EPROM_R_SHIFT 0
-#define CONFIG2_DMA_POLLING_MODE_SHIFT 3
-
-#define INTA_TXOVERFLOW (1<<15)
-#define INTA_TIMEOUT (1<<14)
-#define INTA_HIPRIORITYDESCERR (1<<9)
-#define INTA_HIPRIORITYDESCOK (1<<8)
-#define INTA_NORMPRIORITYDESCERR (1<<7)
-#define INTA_NORMPRIORITYDESCOK (1<<6)
-#define INTA_RXOVERFLOW (1<<5)
-#define INTA_RXDESCERR (1<<4)
-#define INTA_LOWPRIORITYDESCERR (1<<3)
-#define INTA_LOWPRIORITYDESCOK (1<<2)
-#define INTA_RXOK (1)
-#define INTA_MASK 0x3c
-
-#define RXRING_ADDR 0xe4 /* page 0 */
-#define PGSELECT 0x5e
-#define PGSELECT_PG_SHIFT 0
-#define RX_CONF 0x44
-#define MAC_FILTER_MASK ((1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<5) | \
-(1<<12) | (1<<18) | (1<<19) | (1<<20) | (1<<21) | (1<<22) | (1<<23))
-#define RX_CHECK_BSSID_SHIFT 23
-#define ACCEPT_PWR_FRAME_SHIFT 22
-#define ACCEPT_MNG_FRAME_SHIFT 20
-#define ACCEPT_CTL_FRAME_SHIFT 19
-#define ACCEPT_DATA_FRAME_SHIFT 18
-#define ACCEPT_ICVERR_FRAME_SHIFT 12
-#define ACCEPT_CRCERR_FRAME_SHIFT 5
-#define ACCEPT_BCAST_FRAME_SHIFT 3
-#define ACCEPT_MCAST_FRAME_SHIFT 2
-#define ACCEPT_ALLMAC_FRAME_SHIFT 0
-#define ACCEPT_NICMAC_FRAME_SHIFT 1
-
-#define RX_FIFO_THRESHOLD_MASK ((1<<13) | (1<<14) | (1<<15))
-#define RX_FIFO_THRESHOLD_SHIFT 13
-#define RX_FIFO_THRESHOLD_NONE 7
-#define RX_AUTORESETPHY_SHIFT 28
-
-#define TX_CONF 0x40
-#define TX_CONF_HEADER_AUTOICREMENT_SHIFT 30
-#define TX_LOOPBACK_SHIFT 17
-#define TX_LOOPBACK_NONE 0
-#define TX_LOOPBACK_CONTINUE 3
-#define TX_LOOPBACK_MASK ((1<<17)|(1<<18))
-#define TX_DPRETRY_SHIFT 0
-#define R8180_MAX_RETRY 255
-#define TX_RTSRETRY_SHIFT 8
-#define TX_NOICV_SHIFT 19
-#define TX_NOCRC_SHIFT 16
-#define TX_DMA_POLLING 0xd9
-#define TX_DMA_POLLING_BEACON_SHIFT 7
-#define TX_DMA_POLLING_HIPRIORITY_SHIFT 6
-#define TX_DMA_POLLING_NORMPRIORITY_SHIFT 5
-#define TX_DMA_POLLING_LOWPRIORITY_SHIFT 4
-#define TX_MANAGEPRIORITY_RING_ADDR 0x0C
-#define TX_BKPRIORITY_RING_ADDR 0x10
-#define TX_BEPRIORITY_RING_ADDR 0x14
-#define TX_VIPRIORITY_RING_ADDR 0x20
-#define TX_VOPRIORITY_RING_ADDR 0x24
-#define TX_HIGHPRIORITY_RING_ADDR 0x28
-#define MAX_RX_DMA_MASK ((1<<8) | (1<<9) | (1<<10))
-#define MAX_RX_DMA_2048 7
-#define MAX_RX_DMA_1024 6
-#define MAX_RX_DMA_SHIFT 10
-#define INT_TIMEOUT 0x48
-#define CONFIG3_CLKRUN_SHIFT 2
-#define CONFIG3_ANAPARAM_W_SHIFT 6
-#define ANAPARAM 0x54
-#define BEACON_INTERVAL 0x70
-#define BEACON_INTERVAL_MASK ((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)| \
-(1<<6)|(1<<7)|(1<<8)|(1<<9))
-#define ATIM_MASK ((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)| \
-(1<<8)|(1<<9))
-#define ATIM 0x72
-#define EPROM_CS_SHIFT 3
-#define EPROM_CK_SHIFT 2
-#define PHY_ADR 0x7c
-#define SECURITY 0x5f /* 1209 this is sth wrong */
-#define SECURITY_WEP_TX_ENABLE_SHIFT 1
-#define SECURITY_WEP_RX_ENABLE_SHIFT 0
-#define SECURITY_ENCRYP_104 1
-#define SECURITY_ENCRYP_SHIFT 4
-#define SECURITY_ENCRYP_MASK ((1<<4)|(1<<5))
-#define KEY0 0x90 /* 1209 this is sth wrong */
-#define CONFIG2_ANTENNA_SHIFT 6
-#define TX_BEACON_RING_ADDR 0x4c
-#define CONFIG0_WEP40_SHIFT 7
-#define CONFIG0_WEP104_SHIFT 6
-#define AGCRESET_SHIFT 5
-
-
-
-/*
- * Operational registers offsets in PCI (I/O) space.
- * RealTek names are used.
- */
-
-#define TSFTR 0x0018
-
-#define TLPDA 0x0020
-
-#define BSSID 0x002E
-
-#define CR 0x0037
-
-#define RF_SW_CONFIG 0x8 /* store data which is transmitted to RF for driver */
-#define RF_SW_CFG_SI BIT1
-#define EIFS 0x2D /* Extended InterFrame Space Timer, in unit of 4 us. */
-
-#define BRSR 0x34 /* Basic rate set */
-
-#define IMR 0x006C
-#define ISR 0x003C
-
-#define TCR 0x0040
-
-#define RCR 0x0044
-
-#define TimerInt 0x0048
-
-#define CR9346 0x0050
-
-#define CONFIG0 0x0051
-#define CONFIG2 0x0053
-
-#define MSR 0x0058
-
-#define CONFIG3 0x0059
-#define CONFIG4 0x005A
- /* SD3 szuyitasi: Mac0x57= CC -> B0 Mac0x60= D1 -> C6 */
- /* Mac0x60 = 0x000004C6 power save parameters */
- #define ANAPARM_ASIC_ON 0xB0054D00
- #define ANAPARM2_ASIC_ON 0x000004C6
-
- #define ANAPARM_ON ANAPARM_ASIC_ON
- #define ANAPARM2_ON ANAPARM2_ASIC_ON
-
-#define TESTR 0x005B
-
-#define PSR 0x005E
-
-#define BcnItv 0x0070
-
-#define AtimWnd 0x0072
-
-#define BintrItv 0x0074
-
-#define PhyAddr 0x007C
-#define PhyDataR 0x007E
-
-/* following are for rtl8185 */
-#define RFPinsOutput 0x80
-#define RFPinsEnable 0x82
-#define RF_TIMING 0x8c
-#define RFPinsSelect 0x84
-#define ANAPARAM2 0x60
-#define RF_PARA 0x88
-#define RFPinsInput 0x86
-#define GP_ENABLE 0x90
-#define GPIO 0x91
-#define SW_CONTROL_GPIO 0x400
-#define TX_ANTENNA 0x9f
-#define TX_GAIN_OFDM 0x9e
-#define TX_GAIN_CCK 0x9d
-#define WPA_CONFIG 0xb0
-#define TX_AGC_CTL 0x9c
-#define TX_AGC_CTL_PERPACKET_GAIN_SHIFT 0
-#define TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT 1
-#define TX_AGC_CTL_FEEDBACK_ANT 2
-#define RESP_RATE 0x34
-#define SIFS 0xb4
-#define DIFS 0xb5
-
-#define SLOT 0xb6
-#define CW_CONF 0xbc
-#define CW_CONF_PERPACKET_RETRY_SHIFT 1
-#define CW_CONF_PERPACKET_CW_SHIFT 0
-#define CW_VAL 0xbd
-#define MAX_RESP_RATE_SHIFT 4
-#define MIN_RESP_RATE_SHIFT 0
-#define RATE_FALLBACK 0xbe
-
-#define CONFIG5 0x00D8
-
-#define PHYPR 0xDA /* 0xDA - 0x0B PHY Parameter Register. */
-
-#define FEMR 0x1D4 /* Function Event Mask register */
-
-#define FFER 0x00FC
-#define FFER_END 0x00FF
-
-
-
-/*
- * Bitmasks for specific register functions.
- * Names are derived from the register name and function name.
- *
- * <REGISTER>_<FUNCTION>[<bit>]
- *
- * this leads to some awkward names...
- */
-
-#define BRSR_BPLCP ((1 << 8))
-#define BRSR_MBR ((1 << 1)|(1 << 0))
-#define BRSR_MBR_8185 ((1 << 11)|(1 << 10)|(1 << 9)|(1 << 8)|(1 << 7)|(1 << 6)|(1 << 5)|(1 << 4)|(1 << 3)|(1 << 2)|(1 << 1)|(1 << 0))
-#define BRSR_MBR0 ((1 << 0))
-#define BRSR_MBR1 ((1 << 1))
-
-#define CR_RST ((1 << 4))
-#define CR_RE ((1 << 3))
-#define CR_TE ((1 << 2))
-#define CR_MulRW ((1 << 0))
-
-#define IMR_Dot11hInt ((1 << 25)) /*802.11h Measurement Interrupt */
-#define IMR_BcnDmaInt ((1 << 24)) /*Beacon DMA Interrupt */ /*What differenct between BcnDmaInt and BcnInt??? */
-#define IMR_WakeInt ((1 << 23)) /*Wake Up Interrupt */
-#define IMR_TXFOVW ((1 << 22)) /*Tx FIFO Overflow Interrupt */
-#define IMR_TimeOut1 ((1 << 21)) /*Time Out Interrupt 1 */
-#define IMR_BcnInt ((1 << 20)) /*Beacon Time out Interrupt */
-#define IMR_ATIMInt ((1 << 19)) /*ATIM Time Out Interrupt */
-#define IMR_TBDER ((1 << 18)) /*Tx Beacon Descriptor Error Interrupt */
-#define IMR_TBDOK ((1 << 17)) /*Tx Beacon Descriptor OK Interrupt */
-#define IMR_THPDER ((1 << 16)) /*Tx High Priority Descriptor Error Interrupt */
-#define IMR_THPDOK ((1 << 15)) /*Tx High Priority Descriptor OK Interrupt */
-#define IMR_TVODER ((1 << 14)) /*Tx AC_VO Descriptor Error Interrupt */
-#define IMR_TVODOK ((1 << 13)) /*Tx AC_VO Descriptor OK Interrupt */
-#define IMR_FOVW ((1 << 12)) /*Rx FIFO Overflow Interrupt */
-#define IMR_RDU ((1 << 11)) /*Rx Descriptor Unavailable Interrupt */
-#define IMR_TVIDER ((1 << 10)) /*Tx AC_VI Descriptor Error Interrupt */
-#define IMR_TVIDOK ((1 << 9)) /*Tx AC_VI Descriptor OK Interrupt */
-#define IMR_RER ((1 << 8)) /*Rx Error Interrupt */
-#define IMR_ROK ((1 << 7)) /*Receive OK Interrupt */
-#define IMR_TBEDER ((1 << 6)) /*Tx AC_BE Descriptor Error Interrupt */
-#define IMR_TBEDOK ((1 << 5)) /*Tx AC_BE Descriptor OK Interrupt */
-#define IMR_TBKDER ((1 << 4)) /*Tx AC_BK Descriptor Error Interrupt */
-#define IMR_TBKDOK ((1 << 3)) /*Tx AC_BK Descriptor OK Interrupt */
-#define IMR_RQoSOK ((1 << 2)) /*Rx QoS OK Interrupt */
-#define IMR_TimeOut2 ((1 << 1)) /*Time Out Interrupt 2 */
-#define IMR_TimeOut3 ((1 << 0)) /*Time Out Interrupt 3 */
-#define IMR_TMGDOK ((1 << 30))
-#define ISR_Dot11hInt ((1 << 25)) /*802.11h Measurement Interrupt */
-#define ISR_BcnDmaInt ((1 << 24)) /*Beacon DMA Interrupt */ /*What differenct between BcnDmaInt and BcnInt??? */
-#define ISR_WakeInt ((1 << 23)) /*Wake Up Interrupt */
-#define ISR_TXFOVW ((1 << 22)) /*Tx FIFO Overflow Interrupt */
-#define ISR_TimeOut1 ((1 << 21)) /*Time Out Interrupt 1 */
-#define ISR_BcnInt ((1 << 20)) /*Beacon Time out Interrupt */
-#define ISR_ATIMInt ((1 << 19)) /*ATIM Time Out Interrupt */
-#define ISR_TBDER ((1 << 18)) /*Tx Beacon Descriptor Error Interrupt */
-#define ISR_TBDOK ((1 << 17)) /*Tx Beacon Descriptor OK Interrupt */
-#define ISR_THPDER ((1 << 16)) /*Tx High Priority Descriptor Error Interrupt */
-#define ISR_THPDOK ((1 << 15)) /*Tx High Priority Descriptor OK Interrupt */
-#define ISR_TVODER ((1 << 14)) /*Tx AC_VO Descriptor Error Interrupt */
-#define ISR_TVODOK ((1 << 13)) /*Tx AC_VO Descriptor OK Interrupt */
-#define ISR_FOVW ((1 << 12)) /*Rx FIFO Overflow Interrupt */
-#define ISR_RDU ((1 << 11)) /*Rx Descriptor Unavailable Interrupt */
-#define ISR_TVIDER ((1 << 10)) /*Tx AC_VI Descriptor Error Interrupt */
-#define ISR_TVIDOK ((1 << 9)) /*Tx AC_VI Descriptor OK Interrupt */
-#define ISR_RER ((1 << 8)) /*Rx Error Interrupt */
-#define ISR_ROK ((1 << 7)) /*Receive OK Interrupt */
-#define ISR_TBEDER ((1 << 6)) /*Tx AC_BE Descriptor Error Interrupt */
-#define ISR_TBEDOK ((1 << 5)) /*Tx AC_BE Descriptor OK Interrupt */
-#define ISR_TBKDER ((1 << 4)) /*Tx AC_BK Descriptor Error Interrupt */
-#define ISR_TBKDOK ((1 << 3)) /*Tx AC_BK Descriptor OK Interrupt */
-#define ISR_RQoSOK ((1 << 2)) /*Rx QoS OK Interrupt */
-#define ISR_TimeOut2 ((1 << 1)) /*Time Out Interrupt 2 */
-#define ISR_TimeOut3 ((1 << 0)) /*Time Out Interrupt 3 */
-
-/* these definition is used for Tx/Rx test temporarily */
-#define ISR_TLPDER ISR_TVIDER
-#define ISR_TLPDOK ISR_TVIDOK
-#define ISR_TNPDER ISR_TVODER
-#define ISR_TNPDOK ISR_TVODOK
-#define ISR_TimeOut ISR_TimeOut1
-#define ISR_RXFOVW ISR_FOVW
-
-
-#define HW_VERID_R8180_F 3
-#define HW_VERID_R8180_ABCD 2
-#define HW_VERID_R8185_ABC 4
-#define HW_VERID_R8185_D 5
-#define HW_VERID_R8185B_B 6
-
-#define TCR_CWMIN ((1 << 31))
-#define TCR_SWSEQ ((1 << 30))
-#define TCR_HWVERID_MASK ((1 << 27)|(1 << 26)|(1 << 25))
-#define TCR_HWVERID_SHIFT 25
-#define TCR_SAT ((1 << 24))
-#define TCR_PLCP_LEN TCR_SAT /* rtl8180 */
-#define TCR_MXDMA_MASK ((1 << 23)|(1 << 22)|(1 << 21))
-#define TCR_MXDMA_1024 6
-#define TCR_MXDMA_2048 7
-#define TCR_MXDMA_SHIFT 21
-#define TCR_DISCW ((1 << 20))
-#define TCR_ICV ((1 << 19))
-#define TCR_LBK ((1 << 18)|(1 << 17))
-#define TCR_LBK1 ((1 << 18))
-#define TCR_LBK0 ((1 << 17))
-#define TCR_CRC ((1 << 16))
-#define TCR_DPRETRY_MASK ((1 << 15)|(1 << 14)|(1 << 13)|(1 << 12)|(1 << 11)|(1 << 10)|(1 << 9)|(1 << 8))
-#define TCR_RTSRETRY_MASK ((1 << 0)|(1 << 1)|(1 << 2)|(1 << 3)|(1 << 4)|(1 << 5)|(1 << 6)|(1 << 7))
-#define TCR_PROBE_NOTIMESTAMP_SHIFT 29 /* rtl8185 */
-
-#define RCR_ONLYERLPKT ((1 << 31))
-#define RCR_CS_SHIFT 29
-#define RCR_CS_MASK ((1 << 30) | (1 << 29))
-#define RCR_ENMARP ((1 << 28))
-#define RCR_CBSSID ((1 << 23))
-#define RCR_APWRMGT ((1 << 22))
-#define RCR_ADD3 ((1 << 21))
-#define RCR_AMF ((1 << 20))
-#define RCR_ACF ((1 << 19))
-#define RCR_ADF ((1 << 18))
-#define RCR_RXFTH ((1 << 15)|(1 << 14)|(1 << 13))
-#define RCR_RXFTH2 ((1 << 15))
-#define RCR_RXFTH1 ((1 << 14))
-#define RCR_RXFTH0 ((1 << 13))
-#define RCR_AICV ((1 << 12))
-#define RCR_MXDMA ((1 << 10)|(1 << 9)|(1 << 8))
-#define RCR_MXDMA2 ((1 << 10))
-#define RCR_MXDMA1 ((1 << 9))
-#define RCR_MXDMA0 ((1 << 8))
-#define RCR_9356SEL ((1 << 6))
-#define RCR_ACRC32 ((1 << 5))
-#define RCR_AB ((1 << 3))
-#define RCR_AM ((1 << 2))
-#define RCR_APM ((1 << 1))
-#define RCR_AAP ((1 << 0))
-
-#define CR9346_EEM ((1 << 7)|(1 << 6))
-#define CR9346_EEM1 ((1 << 7))
-#define CR9346_EEM0 ((1 << 6))
-#define CR9346_EECS ((1 << 3))
-#define CR9346_EESK ((1 << 2))
-#define CR9346_EED1 ((1 << 1))
-#define CR9346_EED0 ((1 << 0))
-
-#define CONFIG3_PARM_En ((1 << 6))
-#define CONFIG3_FuncRegEn ((1 << 1))
-
-#define CONFIG4_PWRMGT ((1 << 5))
-
-#define MSR_LINK_MASK ((1 << 2)|(1 << 3))
-#define MSR_LINK_MANAGED 2
-#define MSR_LINK_NONE 0
-#define MSR_LINK_SHIFT 2
-#define MSR_LINK_ADHOC 1
-#define MSR_LINK_MASTER 3
-
-#define BcnItv_BcnItv (0x01FF)
-
-#define AtimWnd_AtimWnd (0x01FF)
-
-#define BintrItv_BintrItv (0x01FF)
-
-#define FEMR_INTR ((1 << 15))
-#define FEMR_WKUP ((1 << 14))
-#define FEMR_GWAKE ((1 << 4))
-
-#define FFER_INTR ((1 << 15))
-#define FFER_GWAKE ((1 << 4))
-
-/* Three wire mode. */
-#define SW_THREE_WIRE 0
-#define HW_THREE_WIRE 2
-/* RTL8187S by amy */
-#define HW_THREE_WIRE_PI 5
-#define HW_THREE_WIRE_SI 6
-/* by amy */
-#define TCR_LRL_OFFSET 0
-#define TCR_SRL_OFFSET 8
-#define TCR_MXDMA_OFFSET 21
-#define TCR_DISReqQsize_OFFSET 28
-#define TCR_DurProcMode_OFFSET 30
-
-#define RCR_MXDMA_OFFSET 8
-#define RCR_FIFO_OFFSET 13
-
-#define AckTimeOutReg 0x79 /* ACK timeout register, in unit of 4 us. */
-
-#define RFTiming 0x8C
-
-#define TPPollStop 0x93
-
-#define TXAGC_CTL 0x9C /*< RJ_TODO_8185B> TX_AGC_CONTROL (0x9C seems be removed at 8185B, see p37). */
-#define CCK_TXAGC 0x9D
-#define OFDM_TXAGC 0x9E
-#define ANTSEL 0x9F
-
-#define ACM_CONTROL 0x00BF /* ACM Control Registe */
-
-#define IntMig 0xE2 /* Interrupt Migration (0xE2 ~ 0xE3) */
-
-#define TID_AC_MAP 0xE8 /* TID to AC Mapping Register */
-
-#define ANAPARAM3 0xEE /* <RJ_TODO_8185B> How to use it? */
-
-#define AC_VO_PARAM 0xF0 /* AC_VO Parameters Record */
-#define AC_VI_PARAM 0xF4 /* AC_VI Parameters Record */
-#define AC_BE_PARAM 0xF8 /* AC_BE Parameters Record */
-#define AC_BK_PARAM 0xFC /* AC_BK Parameters Record */
-
-#define GPIOCtrl 0x16B /*GPIO Control Register. */
-#define ARFR 0x1E0 /* Auto Rate Fallback Register (0x1e0 ~ 0x1e2) */
-
-#define RFSW_CTRL 0x272 /* 0x272-0x273. */
-#define SW_3W_DB0 0x274 /* Software 3-wire data buffer bit 31~0. */
-#define SW_3W_DB1 0x278 /* Software 3-wire data buffer bit 63~32. */
-#define SW_3W_CMD0 0x27C /* Software 3-wire Control/Status Register. */
-#define SW_3W_CMD1 0x27D /* Software 3-wire Control/Status Register. */
-
-#define PI_DATA_READ 0X360 /* 0x360 - 0x361 Parallel Interface Data Register. */
-#define SI_DATA_READ 0x362 /* 0x362 - 0x363 Serial Interface Data Register. */
-
-/*
-----------------------------------------------------------------------------
- 8185B TPPollStop bits (offset 0x93, 1 byte)
-----------------------------------------------------------------------------
-*/
-#define TPPOLLSTOP_BQ (0x01 << 7)
-#define TPPOLLSTOP_AC_VIQ (0x01 << 4)
-
-#define MSR_LINK_ENEDCA (1<<4)
-
-/*
-----------------------------------------------------------------------------
- 8187B AC_XX_PARAM bits
-----------------------------------------------------------------------------
-*/
-#define AC_PARAM_TXOP_LIMIT_OFFSET 16
-#define AC_PARAM_ECW_MAX_OFFSET 12
-#define AC_PARAM_ECW_MIN_OFFSET 8
-#define AC_PARAM_AIFS_OFFSET 0
-
-/*
-----------------------------------------------------------------------------
- 8187B ACM_CONTROL bits (Offset 0xBF, 1 Byte)
-----------------------------------------------------------------------------
-*/
-#define VOQ_ACM_EN (0x01 << 7) /*BIT7 */
-#define VIQ_ACM_EN (0x01 << 6) /*BIT6 */
-#define BEQ_ACM_EN (0x01 << 5) /*BIT5 */
-#define ACM_HW_EN (0x01 << 4) /*BIT4 */
-#define VOQ_ACM_CTL (0x01 << 2) /*BIT2 */ /* Set to 1 when AC_VO used time reaches or exceeds the admitted time */
-#define VIQ_ACM_CTL (0x01 << 1) /*BIT1 */ /* Set to 1 when AC_VI used time reaches or exceeds the admitted time */
-#define BEQ_ACM_CTL (0x01 << 0) /*BIT0 */ /* Set to 1 when AC_BE used time reaches or exceeds the admitted time */
-
-
-/*
-----------------------------------------------------------------------------
- 8185B SW_3W_CMD bits (Offset 0x27C-0x27D, 16bit)
-----------------------------------------------------------------------------
-*/
-#define SW_3W_CMD0_HOLD ((1 << 7))
-#define SW_3W_CMD1_RE ((1 << 0)) /* BIT8 */
-#define SW_3W_CMD1_WE ((1 << 1)) /* BIT9 */
-#define SW_3W_CMD1_DONE ((1 << 2)) /* BIT10 */
-
-#define BB_HOST_BANG_RW (1 << 3)
-
-/*
-----------------------------------------------------------------------------
- 8185B RATE_FALLBACK_CTL bits (Offset 0xBE, 8bit)
-----------------------------------------------------------------------------
-*/
-#define RATE_FALLBACK_CTL_ENABLE ((1 << 7))
-#define RATE_FALLBACK_CTL_ENABLE_RTSCTS ((1 << 6))
-/* Auto rate fallback per 2^n retry. */
-#define RATE_FALLBACK_CTL_AUTO_STEP0 0x00
-#define RATE_FALLBACK_CTL_AUTO_STEP1 0x01
-#define RATE_FALLBACK_CTL_AUTO_STEP2 0x02
-#define RATE_FALLBACK_CTL_AUTO_STEP3 0x03
-
-
-#define RTL8225z2_ANAPARAM_OFF 0x55480658
-#define RTL8225z2_ANAPARAM2_OFF 0x72003f70
-/* by amy for power save */
-#define RF_CHANGE_BY_HW BIT30
-#define RF_CHANGE_BY_PS BIT29
-#define RF_CHANGE_BY_IPS BIT28
-/* by amy for power save */
-/* by amy for antenna */
-#define EEPROM_SW_REVD_OFFSET 0x3f
-
-/* BIT[8-9] is for SW Antenna Diversity.
- * Only the value EEPROM_SW_AD_ENABLE means enable, other values are disable.
- */
-#define EEPROM_SW_AD_MASK 0x0300
-#define EEPROM_SW_AD_ENABLE 0x0100
-
-/* BIT[10-11] determine if Antenna 1 is the Default Antenna.
- * Only the value EEPROM_DEF_ANT_1 means TRUE, other values are FALSE.
- */
-#define EEPROM_DEF_ANT_MASK 0x0C00
-#define EEPROM_DEF_ANT_1 0x0400
-/*by amy for antenna */
-/* {by amy 080312 */
-/* 0x7C, 0x7D Crystal calibration and Tx Power tracking mechanism. Added by Roger. 2007.12.10. */
-#define EEPROM_RSV 0x7C
-#define EEPROM_XTAL_CAL_XOUT_MASK 0x0F /* 0x7C[3:0], Crystal calibration for Xout. */
-#define EEPROM_XTAL_CAL_XIN_MASK 0xF0 /* 0x7C[7:4], Crystal calibration for Xin. */
-#define EEPROM_THERMAL_METER_MASK 0x0F00 /* 0x7D[3:0], Thermal meter reference level. */
-#define EEPROM_XTAL_CAL_ENABLE 0x1000 /* 0x7D[4], Crystal calibration enabled/disabled BIT. */
-#define EEPROM_THERMAL_METER_ENABLE 0x2000 /* 0x7D[5], Thermal meter enabled/disabled BIT. */
-#define EN_LPF_CAL 0x238 /* Enable LPF Calibration. */
-#define PWR_METER_EN BIT1
-/* <RJ_TODO_8185B> where are false alarm counters in 8185B? */
-#define CCK_FALSE_ALARM 0xD0
-/* by amy 080312} */
-
-/* YJ,add for Country IE, 080630 */
-#define EEPROM_COUNTRY_CODE 0x2E
-/* YJ,add,080630,end */
-
-#endif
diff --git a/drivers/staging/rtl8187se/r8180_rtl8225.h b/drivers/staging/rtl8187se/r8180_rtl8225.h
deleted file mode 100644
index 7df73927b3cc..000000000000
--- a/drivers/staging/rtl8187se/r8180_rtl8225.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * This is part of the rtl8180-sa2400 driver released under the GPL (See file
- * COPYING for details).
- *
- * Copyright (c) 2005 Andrea Merello <andrea.merello@gmail.com>
- *
- * This files contains programming code for the rtl8225 radio frontend.
- *
- * *Many* thanks to Realtek Corp. for their great support!
- */
-
-#include "r8180.h"
-
-#define RTL8225_ANAPARAM_ON 0xa0000b59
-#define RTL8225_ANAPARAM_OFF 0xa00beb59
-#define RTL8225_ANAPARAM2_OFF 0x840dec11
-#define RTL8225_ANAPARAM2_ON 0x860dec11
-#define RTL8225_ANAPARAM_SLEEP 0xa00bab59
-#define RTL8225_ANAPARAM2_SLEEP 0x840dec11
-
-void rtl8225z2_rf_init(struct net_device *dev);
-void rtl8225z2_rf_set_chan(struct net_device *dev, short ch);
-void rtl8225z2_rf_close(struct net_device *dev);
-
-void RF_WriteReg(struct net_device *dev, u8 offset, u16 data);
-u16 RF_ReadReg(struct net_device *dev, u8 offset);
-
-void rtl8180_set_mode(struct net_device *dev, int mode);
-void rtl8180_set_mode(struct net_device *dev, int mode);
-bool SetZebraRFPowerState8185(struct net_device *dev,
- enum rt_rf_power_state eRFPowerState);
-void rtl8225z4_rf_sleep(struct net_device *dev);
-void rtl8225z4_rf_wakeup(struct net_device *dev);
-
diff --git a/drivers/staging/rtl8187se/r8180_rtl8225z2.c b/drivers/staging/rtl8187se/r8180_rtl8225z2.c
deleted file mode 100644
index 47104fa05c55..000000000000
--- a/drivers/staging/rtl8187se/r8180_rtl8225z2.c
+++ /dev/null
@@ -1,811 +0,0 @@
-/*
- * This is part of the rtl8180-sa2400 driver
- * released under the GPL (See file COPYING for details).
- * Copyright (c) 2005 Andrea Merello <andrea.merello@gmail.com>
- *
- * This files contains programming code for the rtl8225
- * radio frontend.
- *
- * *Many* thanks to Realtek Corp. for their great support!
- */
-
-#include "r8180_hw.h"
-#include "r8180_rtl8225.h"
-#include "r8180_93cx6.h"
-
-#include "ieee80211/dot11d.h"
-
-static void write_rtl8225(struct net_device *dev, u8 adr, u16 data)
-{
- int i;
- u16 out, select;
- u8 bit;
- u32 bangdata = (data << 4) | (adr & 0xf);
-
- out = read_nic_word(dev, RFPinsOutput) & 0xfff3;
-
- write_nic_word(dev, RFPinsEnable,
- (read_nic_word(dev, RFPinsEnable) | 0x7));
-
- select = read_nic_word(dev, RFPinsSelect);
-
- write_nic_word(dev, RFPinsSelect, select | 0x7 |
- SW_CONTROL_GPIO);
-
- force_pci_posting(dev);
- udelay(10);
-
- write_nic_word(dev, RFPinsOutput, out | BB_HOST_BANG_EN);
-
- force_pci_posting(dev);
- udelay(2);
-
- write_nic_word(dev, RFPinsOutput, out);
-
- force_pci_posting(dev);
- udelay(10);
-
- for (i = 15; i >= 0; i--) {
- bit = (bangdata & (1 << i)) >> i;
-
- write_nic_word(dev, RFPinsOutput, bit | out);
-
- write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK);
- write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK);
-
- i--;
- bit = (bangdata & (1 << i)) >> i;
-
- write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK);
- write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK);
-
- write_nic_word(dev, RFPinsOutput, bit | out);
-
- }
-
- write_nic_word(dev, RFPinsOutput, out | BB_HOST_BANG_EN);
-
- force_pci_posting(dev);
- udelay(10);
-
- write_nic_word(dev, RFPinsOutput, out | BB_HOST_BANG_EN);
-
- write_nic_word(dev, RFPinsSelect, select | SW_CONTROL_GPIO);
-
- rtl8185_rf_pins_enable(dev);
-}
-
-static const u8 rtl8225_agc[] = {
- 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
- 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96,
- 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e,
- 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86,
- 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e,
- 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36,
- 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e,
- 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26,
- 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e,
- 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16,
- 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e,
- 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06,
- 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-};
-
-static const u32 rtl8225_chan[] = {
- 0,
- 0x0080, 0x0100, 0x0180, 0x0200, 0x0280, 0x0300, 0x0380,
- 0x0400, 0x0480, 0x0500, 0x0580, 0x0600, 0x0680, 0x074A,
-};
-
-static const u8 rtl8225z2_gain_bg[] = {
- 0x23, 0x15, 0xa5, /* -82-1dBm */
- 0x23, 0x15, 0xb5, /* -82-2dBm */
- 0x23, 0x15, 0xc5, /* -82-3dBm */
- 0x33, 0x15, 0xc5, /* -78dBm */
- 0x43, 0x15, 0xc5, /* -74dBm */
- 0x53, 0x15, 0xc5, /* -70dBm */
- 0x63, 0x15, 0xc5, /* -66dBm */
-};
-
-static const u8 rtl8225z2_gain_a[] = {
- 0x13, 0x27, 0x5a, /* -82dBm */
- 0x23, 0x23, 0x58, /* -82dBm */
- 0x33, 0x1f, 0x56, /* -82dBm */
- 0x43, 0x1b, 0x54, /* -78dBm */
- 0x53, 0x17, 0x51, /* -74dBm */
- 0x63, 0x24, 0x4f, /* -70dBm */
- 0x73, 0x0f, 0x4c, /* -66dBm */
-};
-
-static const u16 rtl8225z2_rxgain[] = {
- 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
- 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
- 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
- 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
- 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
- 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
- 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
- 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
- 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
- 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
- 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
- 0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb
-
-};
-
-static void rtl8225z2_set_gain(struct net_device *dev, short gain)
-{
- const u8 *rtl8225_gain;
- struct r8180_priv *priv = ieee80211_priv(dev);
- u8 mode = priv->ieee80211->mode;
-
- if (mode == IEEE_B || mode == IEEE_G)
- rtl8225_gain = rtl8225z2_gain_bg;
- else
- rtl8225_gain = rtl8225z2_gain_a;
-
- write_phy_ofdm(dev, 0x0b, rtl8225_gain[gain * 3]);
- write_phy_ofdm(dev, 0x1b, rtl8225_gain[gain * 3 + 1]);
- write_phy_ofdm(dev, 0x1d, rtl8225_gain[gain * 3 + 2]);
- write_phy_ofdm(dev, 0x21, 0x37);
-}
-
-static u32 read_rtl8225(struct net_device *dev, u8 adr)
-{
- u32 data2Write = ((u32)(adr & 0x1f)) << 27;
- u32 dataRead;
- u32 mask;
- u16 oval, oval2, oval3, tmp;
- int i;
- short bit, rw;
- u8 wLength = 6;
- u8 rLength = 12;
- u8 low2high = 0;
-
- oval = read_nic_word(dev, RFPinsOutput);
- oval2 = read_nic_word(dev, RFPinsEnable);
- oval3 = read_nic_word(dev, RFPinsSelect);
-
- write_nic_word(dev, RFPinsEnable, (oval2|0xf));
- write_nic_word(dev, RFPinsSelect, (oval3|0xf));
-
- dataRead = 0;
-
- oval &= ~0xf;
-
- write_nic_word(dev, RFPinsOutput, oval | BB_HOST_BANG_EN);
- udelay(4);
-
- write_nic_word(dev, RFPinsOutput, oval);
- udelay(5);
-
- rw = 0;
-
- mask = (low2high) ? 0x01 : (((u32)0x01)<<(32-1));
-
- for (i = 0; i < wLength/2; i++) {
- bit = ((data2Write&mask) != 0) ? 1 : 0;
- write_nic_word(dev, RFPinsOutput, bit | oval | rw);
- udelay(1);
-
- write_nic_word(dev, RFPinsOutput,
- bit | oval | BB_HOST_BANG_CLK | rw);
- udelay(2);
- write_nic_word(dev, RFPinsOutput,
- bit | oval | BB_HOST_BANG_CLK | rw);
- udelay(2);
-
- mask = (low2high) ? (mask<<1) : (mask>>1);
-
- if (i == 2) {
- rw = BB_HOST_BANG_RW;
- write_nic_word(dev, RFPinsOutput,
- bit | oval | BB_HOST_BANG_CLK | rw);
- udelay(2);
- write_nic_word(dev, RFPinsOutput, bit | oval | rw);
- udelay(2);
- break;
- }
-
- bit = ((data2Write&mask) != 0) ? 1 : 0;
-
- write_nic_word(dev, RFPinsOutput,
- oval | bit | rw | BB_HOST_BANG_CLK);
- udelay(2);
- write_nic_word(dev, RFPinsOutput,
- oval | bit | rw | BB_HOST_BANG_CLK);
- udelay(2);
-
- write_nic_word(dev, RFPinsOutput, oval | bit | rw);
- udelay(1);
-
- mask = (low2high) ? (mask<<1) : (mask>>1);
- }
-
- write_nic_word(dev, RFPinsOutput, rw|oval);
- udelay(2);
- mask = (low2high) ? 0x01 : (((u32)0x01) << (12-1));
-
- /*
- * We must set data pin to HW controlled, otherwise RF can't driver it
- * and value RF register won't be able to read back properly.
- */
- write_nic_word(dev, RFPinsEnable, (oval2 & (~0x01)));
-
- for (i = 0; i < rLength; i++) {
- write_nic_word(dev, RFPinsOutput, rw|oval); udelay(1);
-
- write_nic_word(dev, RFPinsOutput, rw|oval|BB_HOST_BANG_CLK);
- udelay(2);
- write_nic_word(dev, RFPinsOutput, rw|oval|BB_HOST_BANG_CLK);
- udelay(2);
- write_nic_word(dev, RFPinsOutput, rw|oval|BB_HOST_BANG_CLK);
- udelay(2);
- tmp = read_nic_word(dev, RFPinsInput);
-
- dataRead |= (tmp & BB_HOST_BANG_CLK ? mask : 0);
-
- write_nic_word(dev, RFPinsOutput, (rw|oval)); udelay(2);
-
- mask = (low2high) ? (mask<<1) : (mask>>1);
- }
-
- write_nic_word(dev, RFPinsOutput,
- BB_HOST_BANG_EN | BB_HOST_BANG_RW | oval);
- udelay(2);
-
- write_nic_word(dev, RFPinsEnable, oval2);
- write_nic_word(dev, RFPinsSelect, oval3); /* Set To SW Switch */
- write_nic_word(dev, RFPinsOutput, 0x3a0);
-
- return dataRead;
-}
-
-void rtl8225z2_rf_close(struct net_device *dev)
-{
- RF_WriteReg(dev, 0x4, 0x1f);
-
- force_pci_posting(dev);
- mdelay(1);
-
- rtl8180_set_anaparam(dev, RTL8225z2_ANAPARAM_OFF);
- rtl8185_set_anaparam2(dev, RTL8225z2_ANAPARAM2_OFF);
-}
-
-/*
- * Map dBm into Tx power index according to current HW model, for example,
- * RF and PA, and current wireless mode.
- */
-static s8 DbmToTxPwrIdx(struct r8180_priv *priv,
- enum wireless_mode mode, s32 PowerInDbm)
-{
- bool bUseDefault = true;
- s8 TxPwrIdx = 0;
-
- /*
- * OFDM Power in dBm = Index * 0.5 + 0
- * CCK Power in dBm = Index * 0.25 + 13
- */
- s32 tmp = 0;
-
- if (mode == WIRELESS_MODE_G) {
- bUseDefault = false;
- tmp = (2 * PowerInDbm);
-
- if (tmp < 0)
- TxPwrIdx = 0;
- else if (tmp > 40) /* 40 means 20 dBm. */
- TxPwrIdx = 40;
- else
- TxPwrIdx = (s8)tmp;
- } else if (mode == WIRELESS_MODE_B) {
- bUseDefault = false;
- tmp = (4 * PowerInDbm) - 52;
-
- if (tmp < 0)
- TxPwrIdx = 0;
- else if (tmp > 28) /* 28 means 20 dBm. */
- TxPwrIdx = 28;
- else
- TxPwrIdx = (s8)tmp;
- }
-
- /*
- * TRUE if we want to use a default implementation.
- * We shall set it to FALSE when we have exact translation formula
- * for target IC. 070622, by rcnjko.
- */
- if (bUseDefault) {
- if (PowerInDbm < 0)
- TxPwrIdx = 0;
- else if (PowerInDbm > 35)
- TxPwrIdx = 35;
- else
- TxPwrIdx = (u8)PowerInDbm;
- }
-
- return TxPwrIdx;
-}
-
-void rtl8225z2_SetTXPowerLevel(struct net_device *dev, short ch)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- u8 max_cck_power_level;
- u8 max_ofdm_power_level;
- u8 min_ofdm_power_level;
- char cck_power_level = (char)(0xff & priv->chtxpwr[ch]);
- char ofdm_power_level = (char)(0xff & priv->chtxpwr_ofdm[ch]);
-
- if (IS_DOT11D_ENABLE(priv->ieee80211) &&
- IS_DOT11D_STATE_DONE(priv->ieee80211)) {
- u8 MaxTxPwrInDbm = DOT11D_GetMaxTxPwrInDbm(priv->ieee80211, ch);
- u8 CckMaxPwrIdx = DbmToTxPwrIdx(priv, WIRELESS_MODE_B,
- MaxTxPwrInDbm);
- u8 OfdmMaxPwrIdx = DbmToTxPwrIdx(priv, WIRELESS_MODE_G,
- MaxTxPwrInDbm);
-
- if (cck_power_level > CckMaxPwrIdx)
- cck_power_level = CckMaxPwrIdx;
- if (ofdm_power_level > OfdmMaxPwrIdx)
- ofdm_power_level = OfdmMaxPwrIdx;
- }
-
- max_cck_power_level = 15;
- max_ofdm_power_level = 25;
- min_ofdm_power_level = 10;
-
- if (cck_power_level > 35)
- cck_power_level = 35;
-
- write_nic_byte(dev, CCK_TXAGC, cck_power_level);
- force_pci_posting(dev);
- mdelay(1);
-
- if (ofdm_power_level > 35)
- ofdm_power_level = 35;
-
- if (priv->up == 0) {
- write_phy_ofdm(dev, 2, 0x42);
- write_phy_ofdm(dev, 5, 0x00);
- write_phy_ofdm(dev, 6, 0x40);
- write_phy_ofdm(dev, 7, 0x00);
- write_phy_ofdm(dev, 8, 0x40);
- }
-
- write_nic_byte(dev, OFDM_TXAGC, ofdm_power_level);
-
- if (ofdm_power_level <= 11) {
- write_phy_ofdm(dev, 0x07, 0x5c);
- write_phy_ofdm(dev, 0x09, 0x5c);
- }
-
- if (ofdm_power_level <= 17) {
- write_phy_ofdm(dev, 0x07, 0x54);
- write_phy_ofdm(dev, 0x09, 0x54);
- } else {
- write_phy_ofdm(dev, 0x07, 0x50);
- write_phy_ofdm(dev, 0x09, 0x50);
- }
-
- force_pci_posting(dev);
- mdelay(1);
-}
-
-void rtl8225z2_rf_set_chan(struct net_device *dev, short ch)
-{
- rtl8225z2_SetTXPowerLevel(dev, ch);
-
- RF_WriteReg(dev, 0x7, rtl8225_chan[ch]);
-
- if ((RF_ReadReg(dev, 0x7) & 0x0F80) != rtl8225_chan[ch])
- RF_WriteReg(dev, 0x7, rtl8225_chan[ch]);
-
- mdelay(1);
-
- force_pci_posting(dev);
- mdelay(10);
-}
-
-static void rtl8225_host_pci_init(struct net_device *dev)
-{
- write_nic_word(dev, RFPinsOutput, 0x480);
-
- rtl8185_rf_pins_enable(dev);
-
- write_nic_word(dev, RFPinsSelect, 0x88 | SW_CONTROL_GPIO);
-
- write_nic_byte(dev, GP_ENABLE, 0);
-
- force_pci_posting(dev);
- mdelay(200);
-
- /* bit 6 is for RF on/off detection */
- write_nic_word(dev, GP_ENABLE, 0xff & (~(1 << 6)));
-}
-
-void rtl8225z2_rf_init(struct net_device *dev)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- int i;
- short channel = 1;
- u16 brsr;
- u32 data;
-
- priv->chan = channel;
-
- rtl8225_host_pci_init(dev);
-
- write_nic_dword(dev, RF_TIMING, 0x000a8008);
-
- brsr = read_nic_word(dev, BRSR);
-
- write_nic_word(dev, BRSR, 0xffff);
-
- write_nic_dword(dev, RF_PARA, 0x100044);
-
- rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
- write_nic_byte(dev, CONFIG3, 0x44);
- rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
-
- rtl8185_rf_pins_enable(dev);
-
- write_rtl8225(dev, 0x0, 0x2bf); mdelay(1);
- write_rtl8225(dev, 0x1, 0xee0); mdelay(1);
- write_rtl8225(dev, 0x2, 0x44d); mdelay(1);
- write_rtl8225(dev, 0x3, 0x441); mdelay(1);
- write_rtl8225(dev, 0x4, 0x8c3); mdelay(1);
- write_rtl8225(dev, 0x5, 0xc72); mdelay(1);
- write_rtl8225(dev, 0x6, 0xe6); mdelay(1);
- write_rtl8225(dev, 0x7, rtl8225_chan[channel]); mdelay(1);
- write_rtl8225(dev, 0x8, 0x3f); mdelay(1);
- write_rtl8225(dev, 0x9, 0x335); mdelay(1);
- write_rtl8225(dev, 0xa, 0x9d4); mdelay(1);
- write_rtl8225(dev, 0xb, 0x7bb); mdelay(1);
- write_rtl8225(dev, 0xc, 0x850); mdelay(1);
- write_rtl8225(dev, 0xd, 0xcdf); mdelay(1);
- write_rtl8225(dev, 0xe, 0x2b); mdelay(1);
- write_rtl8225(dev, 0xf, 0x114);
-
- mdelay(100);
-
- write_rtl8225(dev, 0x0, 0x1b7);
-
- for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
- write_rtl8225(dev, 0x1, i + 1);
- write_rtl8225(dev, 0x2, rtl8225z2_rxgain[i]);
- }
-
- write_rtl8225(dev, 0x3, 0x80);
- write_rtl8225(dev, 0x5, 0x4);
-
- write_rtl8225(dev, 0x0, 0xb7);
-
- write_rtl8225(dev, 0x2, 0xc4d);
-
- /* FIXME!! rtl8187 we have to check if calibrarion
- * is successful and eventually cal. again (repeat
- * the two write on reg 2)
- */
- data = read_rtl8225(dev, 6);
- if (!(data & 0x00000080)) {
- write_rtl8225(dev, 0x02, 0x0c4d);
- force_pci_posting(dev); mdelay(200);
- write_rtl8225(dev, 0x02, 0x044d);
- force_pci_posting(dev); mdelay(100);
- data = read_rtl8225(dev, 6);
- if (!(data & 0x00000080))
- DMESGW("RF Calibration Failed!!!!\n");
- }
-
- mdelay(200);
-
- write_rtl8225(dev, 0x0, 0x2bf);
-
- for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
- write_phy_ofdm(dev, 0xb, rtl8225_agc[i]);
- mdelay(1);
-
- /* enable writing AGC table */
- write_phy_ofdm(dev, 0xa, i + 0x80);
- mdelay(1);
- }
-
- force_pci_posting(dev);
- mdelay(1);
-
- write_phy_ofdm(dev, 0x00, 0x01); mdelay(1);
- write_phy_ofdm(dev, 0x01, 0x02); mdelay(1);
- write_phy_ofdm(dev, 0x02, 0x62); mdelay(1);
- write_phy_ofdm(dev, 0x03, 0x00); mdelay(1);
- write_phy_ofdm(dev, 0x04, 0x00); mdelay(1);
- write_phy_ofdm(dev, 0x05, 0x00); mdelay(1);
- write_phy_ofdm(dev, 0x06, 0x40); mdelay(1);
- write_phy_ofdm(dev, 0x07, 0x00); mdelay(1);
- write_phy_ofdm(dev, 0x08, 0x40); mdelay(1);
- write_phy_ofdm(dev, 0x09, 0xfe); mdelay(1);
- write_phy_ofdm(dev, 0x0a, 0x08); mdelay(1);
- write_phy_ofdm(dev, 0x0b, 0x80); mdelay(1);
- write_phy_ofdm(dev, 0x0c, 0x01); mdelay(1);
- write_phy_ofdm(dev, 0x0d, 0x43);
- write_phy_ofdm(dev, 0x0e, 0xd3); mdelay(1);
- write_phy_ofdm(dev, 0x0f, 0x38); mdelay(1);
- write_phy_ofdm(dev, 0x10, 0x84); mdelay(1);
- write_phy_ofdm(dev, 0x11, 0x07); mdelay(1);
- write_phy_ofdm(dev, 0x12, 0x20); mdelay(1);
- write_phy_ofdm(dev, 0x13, 0x20); mdelay(1);
- write_phy_ofdm(dev, 0x14, 0x00); mdelay(1);
- write_phy_ofdm(dev, 0x15, 0x40); mdelay(1);
- write_phy_ofdm(dev, 0x16, 0x00); mdelay(1);
- write_phy_ofdm(dev, 0x17, 0x40); mdelay(1);
- write_phy_ofdm(dev, 0x18, 0xef); mdelay(1);
- write_phy_ofdm(dev, 0x19, 0x19); mdelay(1);
- write_phy_ofdm(dev, 0x1a, 0x20); mdelay(1);
- write_phy_ofdm(dev, 0x1b, 0x15); mdelay(1);
- write_phy_ofdm(dev, 0x1c, 0x04); mdelay(1);
- write_phy_ofdm(dev, 0x1d, 0xc5); mdelay(1);
- write_phy_ofdm(dev, 0x1e, 0x95); mdelay(1);
- write_phy_ofdm(dev, 0x1f, 0x75); mdelay(1);
- write_phy_ofdm(dev, 0x20, 0x1f); mdelay(1);
- write_phy_ofdm(dev, 0x21, 0x17); mdelay(1);
- write_phy_ofdm(dev, 0x22, 0x16); mdelay(1);
- write_phy_ofdm(dev, 0x23, 0x80); mdelay(1); /* FIXME maybe not needed */
- write_phy_ofdm(dev, 0x24, 0x46); mdelay(1);
- write_phy_ofdm(dev, 0x25, 0x00); mdelay(1);
- write_phy_ofdm(dev, 0x26, 0x90); mdelay(1);
- write_phy_ofdm(dev, 0x27, 0x88); mdelay(1);
-
- rtl8225z2_set_gain(dev, 4);
-
- write_phy_cck(dev, 0x0, 0x98); mdelay(1);
- write_phy_cck(dev, 0x3, 0x20); mdelay(1);
- write_phy_cck(dev, 0x4, 0x7e); mdelay(1);
- write_phy_cck(dev, 0x5, 0x12); mdelay(1);
- write_phy_cck(dev, 0x6, 0xfc); mdelay(1);
- write_phy_cck(dev, 0x7, 0x78); mdelay(1);
- write_phy_cck(dev, 0x8, 0x2e); mdelay(1);
- write_phy_cck(dev, 0x10, 0x93); mdelay(1);
- write_phy_cck(dev, 0x11, 0x88); mdelay(1);
- write_phy_cck(dev, 0x12, 0x47); mdelay(1);
- write_phy_cck(dev, 0x13, 0xd0);
- write_phy_cck(dev, 0x19, 0x00);
- write_phy_cck(dev, 0x1a, 0xa0);
- write_phy_cck(dev, 0x1b, 0x08);
- write_phy_cck(dev, 0x40, 0x86); /* CCK Carrier Sense Threshold */
- write_phy_cck(dev, 0x41, 0x8d); mdelay(1);
- write_phy_cck(dev, 0x42, 0x15); mdelay(1);
- write_phy_cck(dev, 0x43, 0x18); mdelay(1);
- write_phy_cck(dev, 0x44, 0x36); mdelay(1);
- write_phy_cck(dev, 0x45, 0x35); mdelay(1);
- write_phy_cck(dev, 0x46, 0x2e); mdelay(1);
- write_phy_cck(dev, 0x47, 0x25); mdelay(1);
- write_phy_cck(dev, 0x48, 0x1c); mdelay(1);
- write_phy_cck(dev, 0x49, 0x12); mdelay(1);
- write_phy_cck(dev, 0x4a, 0x09); mdelay(1);
- write_phy_cck(dev, 0x4b, 0x04); mdelay(1);
- write_phy_cck(dev, 0x4c, 0x05); mdelay(1);
-
- write_nic_byte(dev, 0x5b, 0x0d); mdelay(1);
-
- rtl8225z2_SetTXPowerLevel(dev, channel);
-
- /* RX antenna default to A */
- write_phy_cck(dev, 0x11, 0x9b); mdelay(1); /* B: 0xDB */
- write_phy_ofdm(dev, 0x26, 0x90); mdelay(1); /* B: 0x10 */
-
- rtl8185_tx_antenna(dev, 0x03); /* B: 0x00 */
-
- /* switch to high-speed 3-wire
- * last digit. 2 for both cck and ofdm
- */
- write_nic_dword(dev, 0x94, 0x15c00002);
- rtl8185_rf_pins_enable(dev);
-
- rtl8225z2_rf_set_chan(dev, priv->chan);
-}
-
-#define MAX_DOZE_WAITING_TIMES_85B 20
-#define MAX_POLLING_24F_TIMES_87SE 10
-#define LPS_MAX_SLEEP_WAITING_TIMES_87SE 5
-
-bool SetZebraRFPowerState8185(struct net_device *dev,
- enum rt_rf_power_state eRFPowerState)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- u8 btCR9346, btConfig3;
- bool bActionAllowed = true, bTurnOffBB = true;
- u8 u1bTmp;
- int i;
- bool bResult = true;
- u8 QueueID;
-
- if (priv->SetRFPowerStateInProgress == true)
- return false;
-
- priv->SetRFPowerStateInProgress = true;
-
- btCR9346 = read_nic_byte(dev, CR9346);
- write_nic_byte(dev, CR9346, (btCR9346 | 0xC0));
-
- btConfig3 = read_nic_byte(dev, CONFIG3);
- write_nic_byte(dev, CONFIG3, (btConfig3 | CONFIG3_PARM_En));
-
- switch (eRFPowerState) {
- case RF_ON:
- write_nic_word(dev, 0x37C, 0x00EC);
-
- /* turn on AFE */
- write_nic_byte(dev, 0x54, 0x00);
- write_nic_byte(dev, 0x62, 0x00);
-
- /* turn on RF */
- RF_WriteReg(dev, 0x0, 0x009f); udelay(500);
- RF_WriteReg(dev, 0x4, 0x0972); udelay(500);
-
- /* turn on RF again */
- RF_WriteReg(dev, 0x0, 0x009f); udelay(500);
- RF_WriteReg(dev, 0x4, 0x0972); udelay(500);
-
- /* turn on BB */
- write_phy_ofdm(dev, 0x10, 0x40);
- write_phy_ofdm(dev, 0x12, 0x40);
-
- /* Avoid power down at init time. */
- write_nic_byte(dev, CONFIG4, priv->RFProgType);
-
- u1bTmp = read_nic_byte(dev, 0x24E);
- write_nic_byte(dev, 0x24E, (u1bTmp & (~(BIT5 | BIT6))));
- break;
- case RF_SLEEP:
- for (QueueID = 0, i = 0; QueueID < 6;) {
- if (get_curr_tx_free_desc(dev, QueueID) ==
- priv->txringcount) {
- QueueID++;
- continue;
- } else {
- priv->TxPollingTimes++;
- if (priv->TxPollingTimes >=
- LPS_MAX_SLEEP_WAITING_TIMES_87SE) {
- bActionAllowed = false;
- break;
- } else
- udelay(10);
- }
- }
-
- if (bActionAllowed) {
- /* turn off BB RXIQ matrix to cut off rx signal */
- write_phy_ofdm(dev, 0x10, 0x00);
- write_phy_ofdm(dev, 0x12, 0x00);
-
- /* turn off RF */
- RF_WriteReg(dev, 0x4, 0x0000);
- RF_WriteReg(dev, 0x0, 0x0000);
-
- /* turn off AFE except PLL */
- write_nic_byte(dev, 0x62, 0xff);
- write_nic_byte(dev, 0x54, 0xec);
-
- mdelay(1);
-
- {
- int i = 0;
- while (true) {
- u8 tmp24F = read_nic_byte(dev, 0x24f);
-
- if ((tmp24F == 0x01) ||
- (tmp24F == 0x09)) {
- bTurnOffBB = true;
- break;
- } else {
- udelay(10);
- i++;
- priv->TxPollingTimes++;
-
- if (priv->TxPollingTimes >= LPS_MAX_SLEEP_WAITING_TIMES_87SE) {
- bTurnOffBB = false;
- break;
- } else
- udelay(10);
- }
- }
- }
-
- if (bTurnOffBB) {
- /* turn off BB */
- u1bTmp = read_nic_byte(dev, 0x24E);
- write_nic_byte(dev, 0x24E,
- (u1bTmp | BIT5 | BIT6));
-
- /* turn off AFE PLL */
- write_nic_byte(dev, 0x54, 0xFC);
- write_nic_word(dev, 0x37C, 0x00FC);
- }
- }
- break;
- case RF_OFF:
- for (QueueID = 0, i = 0; QueueID < 6;) {
- if (get_curr_tx_free_desc(dev, QueueID) ==
- priv->txringcount) {
- QueueID++;
- continue;
- } else {
- udelay(10);
- i++;
- }
-
- if (i >= MAX_DOZE_WAITING_TIMES_85B)
- break;
- }
-
- /* turn off BB RXIQ matrix to cut off rx signal */
- write_phy_ofdm(dev, 0x10, 0x00);
- write_phy_ofdm(dev, 0x12, 0x00);
-
- /* turn off RF */
- RF_WriteReg(dev, 0x4, 0x0000);
- RF_WriteReg(dev, 0x0, 0x0000);
-
- /* turn off AFE except PLL */
- write_nic_byte(dev, 0x62, 0xff);
- write_nic_byte(dev, 0x54, 0xec);
-
- mdelay(1);
-
- {
- int i = 0;
-
- while (true) {
- u8 tmp24F = read_nic_byte(dev, 0x24f);
-
- if ((tmp24F == 0x01) || (tmp24F == 0x09)) {
- bTurnOffBB = true;
- break;
- } else {
- bTurnOffBB = false;
- udelay(10);
- i++;
- }
-
- if (i > MAX_POLLING_24F_TIMES_87SE)
- break;
- }
- }
-
- if (bTurnOffBB) {
- /* turn off BB */
- u1bTmp = read_nic_byte(dev, 0x24E);
- write_nic_byte(dev, 0x24E, (u1bTmp | BIT5 | BIT6));
-
- /* turn off AFE PLL (80M) */
- write_nic_byte(dev, 0x54, 0xFC);
- write_nic_word(dev, 0x37C, 0x00FC);
- }
- break;
- }
-
- btConfig3 &= ~(CONFIG3_PARM_En);
- write_nic_byte(dev, CONFIG3, btConfig3);
-
- btCR9346 &= ~(0xC0);
- write_nic_byte(dev, CR9346, btCR9346);
-
- if (bResult && bActionAllowed)
- priv->eRFPowerState = eRFPowerState;
-
- priv->SetRFPowerStateInProgress = false;
-
- return bResult && bActionAllowed;
-}
-
-void rtl8225z4_rf_sleep(struct net_device *dev)
-{
- MgntActSet_RF_State(dev, RF_SLEEP, RF_CHANGE_BY_PS);
-}
-
-void rtl8225z4_rf_wakeup(struct net_device *dev)
-{
- MgntActSet_RF_State(dev, RF_ON, RF_CHANGE_BY_PS);
-}
diff --git a/drivers/staging/rtl8187se/r8180_wx.c b/drivers/staging/rtl8187se/r8180_wx.c
deleted file mode 100644
index b55249170f18..000000000000
--- a/drivers/staging/rtl8187se/r8180_wx.c
+++ /dev/null
@@ -1,1409 +0,0 @@
-/*
- This file contains wireless extension handlers.
-
- This is part of rtl8180 OpenSource driver.
- Copyright (C) Andrea Merello 2004-2005 <andrea.merello@gmail.com>
- Released under the terms of GPL (General Public Licence)
-
- Parts of this driver are based on the GPL part
- of the official realtek driver.
-
- Parts of this driver are based on the rtl8180 driver skeleton
- from Patric Schenke & Andres Salomon.
-
- Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver.
-
- We want to thanks the Authors of those projects and the Ndiswrapper
- project Authors.
-*/
-
-
-#include "r8180.h"
-#include "r8180_hw.h"
-
-#include <net/iw_handler.h>
-#include "ieee80211/dot11d.h"
-
-static u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000,
- 6000000, 9000000, 12000000, 18000000, 24000000, 36000000, 48000000, 54000000};
-
-#define RATE_COUNT ARRAY_SIZE(rtl8180_rates)
-
-static struct rtl8187se_channel_list default_channel_plan[] = {
- {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 36, 40, 44, 48, 52, 56, 60, 64}, 19}, /* FCC */
- {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11}, /* IC */
- {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56, 60, 64}, 21}, /* ETSI */
- {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56, 60, 64}, 21}, /* Spain. Change to ETSI. */
- {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56, 60, 64}, 21}, /* France. Change to ETSI. */
- {{14, 36, 40, 44, 48, 52, 56, 60, 64}, 9}, /* MKK */
- {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52, 56, 60, 64}, 22}, /* MKK1 */
- {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56, 60, 64}, 21}, /* Israel */
- {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 34, 38, 42, 46}, 17}, /* For 11a , TELEC */
- {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14} /* For Global Domain. 1-11:active scan, 12-14 passive scan.*/ /* +YJ, 080626 */
-};
-static int r8180_wx_get_freq(struct net_device *dev,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *b)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
-
- return ieee80211_wx_get_freq(priv->ieee80211, a, wrqu, b);
-}
-
-
-static int r8180_wx_set_key(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *key)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- struct iw_point *erq = &(wrqu->encoding);
-
- if (priv->ieee80211->bHwRadioOff)
- return 0;
-
- if (erq->length > 0) {
- u32 *tkey = (u32 *) key;
- priv->key0[0] = tkey[0];
- priv->key0[1] = tkey[1];
- priv->key0[2] = tkey[2];
- priv->key0[3] = tkey[3] & 0xff;
- DMESG("Setting wep key to %x %x %x %x",
- tkey[0], tkey[1], tkey[2], tkey[3]);
- rtl8180_set_hw_wep(dev);
- }
- return 0;
-}
-
-
-static int r8180_wx_set_beaconinterval(struct net_device *dev,
- struct iw_request_info *aa,
- union iwreq_data *wrqu, char *b)
-{
- int *parms = (int *)b;
- int bi = parms[0];
-
- struct r8180_priv *priv = ieee80211_priv(dev);
-
- if (priv->ieee80211->bHwRadioOff)
- return 0;
-
- down(&priv->wx_sem);
- DMESG("setting beacon interval to %x", bi);
-
- priv->ieee80211->current_network.beacon_interval = bi;
- rtl8180_commit(dev);
- up(&priv->wx_sem);
-
- return 0;
-}
-
-
-
-static int r8180_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *b)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- return ieee80211_wx_get_mode(priv->ieee80211, a, wrqu, b);
-}
-
-
-
-static int r8180_wx_get_rate(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- return ieee80211_wx_get_rate(priv->ieee80211, info, wrqu, extra);
-}
-
-
-
-static int r8180_wx_set_rate(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- int ret;
- struct r8180_priv *priv = ieee80211_priv(dev);
-
-
- if (priv->ieee80211->bHwRadioOff)
- return 0;
-
- down(&priv->wx_sem);
-
- ret = ieee80211_wx_set_rate(priv->ieee80211, info, wrqu, extra);
-
- up(&priv->wx_sem);
-
- return ret;
-}
-
-
-static int r8180_wx_set_crcmon(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- int *parms = (int *)extra;
- int enable = (parms[0] > 0);
- short prev = priv->crcmon;
-
-
- if (priv->ieee80211->bHwRadioOff)
- return 0;
-
- down(&priv->wx_sem);
-
- if (enable)
- priv->crcmon = 1;
- else
- priv->crcmon = 0;
-
- DMESG("bad CRC in monitor mode are %s",
- priv->crcmon ? "accepted" : "rejected");
-
- if (prev != priv->crcmon && priv->up) {
- rtl8180_down(dev);
- rtl8180_up(dev);
- }
-
- up(&priv->wx_sem);
-
- return 0;
-}
-
-
-static int r8180_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *b)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- int ret;
-
-
- if (priv->ieee80211->bHwRadioOff)
- return 0;
-
- down(&priv->wx_sem);
- if (priv->bInactivePs) {
- if (wrqu->mode == IW_MODE_ADHOC)
- IPSLeave(dev);
- }
- ret = ieee80211_wx_set_mode(priv->ieee80211, a, wrqu, b);
-
- up(&priv->wx_sem);
- return ret;
-}
-
-/* YJ,add,080819,for hidden ap */
-struct iw_range_with_scan_capa {
- /* Informative stuff (to choose between different interface) */
-
- __u32 throughput; /* To give an idea... */
-
- /* In theory this value should be the maximum benchmarked
- * TCP/IP throughput, because with most of these devices the
- * bit rate is meaningless (overhead an co) to estimate how
- * fast the connection will go and pick the fastest one.
- * I suggest people to play with Netperf or any benchmark...
- */
-
- /* NWID (or domain id) */
- __u32 min_nwid; /* Minimal NWID we are able to set */
- __u32 max_nwid; /* Maximal NWID we are able to set */
-
- /* Old Frequency (backward compat - moved lower ) */
- __u16 old_num_channels;
- __u8 old_num_frequency;
-
- /* Scan capabilities */
- __u8 scan_capa;
-};
-/* YJ,add,080819,for hidden ap */
-
-
-static int rtl8180_wx_get_range(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct iw_range *range = (struct iw_range *)extra;
- struct r8180_priv *priv = ieee80211_priv(dev);
- u16 val;
- int i;
-
- wrqu->data.length = sizeof(*range);
- memset(range, 0, sizeof(*range));
-
- /* Let's try to keep this struct in the same order as in
- * linux/include/wireless.h
- */
-
- /* TODO: See what values we can set, and remove the ones we can't
- * set, or fill them with some default data.
- */
-
- /* ~5 Mb/s real (802.11b) */
- range->throughput = 5 * 1000 * 1000;
-
- /* TODO: Not used in 802.11b? */
-/* range->min_nwid; */ /* Minimal NWID we are able to set */
- /* TODO: Not used in 802.11b? */
-/* range->max_nwid; */ /* Maximal NWID we are able to set */
-
- /* Old Frequency (backward compat - moved lower ) */
-/* range->old_num_channels; */
-/* range->old_num_frequency; */
-/* range->old_freq[6]; */ /* Filler to keep "version" at the same offset */
- if (priv->rf_set_sens != NULL)
- range->sensitivity = priv->max_sens; /* signal level threshold range */
-
- range->max_qual.qual = 100;
- /* TODO: Find real max RSSI and stick here */
- range->max_qual.level = 0;
- range->max_qual.noise = -98;
- range->max_qual.updated = 7; /* Updated all three */
-
- range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
- /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
- range->avg_qual.level = 20 + -98;
- range->avg_qual.noise = 0;
- range->avg_qual.updated = 7; /* Updated all three */
-
- range->num_bitrates = RATE_COUNT;
-
- for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
- range->bitrate[i] = rtl8180_rates[i];
-
- range->min_frag = MIN_FRAG_THRESHOLD;
- range->max_frag = MAX_FRAG_THRESHOLD;
-
- range->pm_capa = 0;
-
- range->we_version_compiled = WIRELESS_EXT;
- range->we_version_source = 16;
-
- range->num_channels = 14;
-
- for (i = 0, val = 0; i < 14; i++) {
-
- /* Include only legal frequencies for some countries */
- if ((GET_DOT11D_INFO(priv->ieee80211)->channel_map)[i+1]) {
- range->freq[val].i = i + 1;
- range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
- range->freq[val].e = 1;
- val++;
- } else {
- /* FIXME: do we need to set anything for channels */
- /* we don't use ? */
- }
-
- if (val == IW_MAX_FREQUENCIES)
- break;
- }
-
- range->num_frequency = val;
- range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
- IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
-
- return 0;
-}
-
-
-static int r8180_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *b)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- int ret;
- struct ieee80211_device *ieee = priv->ieee80211;
-
-
- if (priv->ieee80211->bHwRadioOff)
- return 0;
-
- if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
- struct iw_scan_req *req = (struct iw_scan_req *)b;
- if (req->essid_len) {
- ieee->current_network.ssid_len = req->essid_len;
- memcpy(ieee->current_network.ssid, req->essid, req->essid_len);
- }
- }
-
- down(&priv->wx_sem);
- if (priv->up) {
- priv->ieee80211->actscanning = true;
- if (priv->bInactivePs && (priv->ieee80211->state != IEEE80211_LINKED)) {
- IPSLeave(dev);
- ieee80211_softmac_ips_scan_syncro(priv->ieee80211);
- ret = 0;
- } else {
- /* prevent scan in BusyTraffic */
- /* FIXME: Need to consider last scan time */
- if ((priv->link_detect.b_busy_traffic) && (true)) {
- ret = 0;
- printk("Now traffic is busy, please try later!\n");
- } else
- /* prevent scan in BusyTraffic,end */
- ret = ieee80211_wx_set_scan(priv->ieee80211, a, wrqu, b);
- }
- } else
- ret = -1;
-
- up(&priv->wx_sem);
-
- return ret;
-}
-
-
-static int r8180_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *b)
-{
-
- int ret;
- struct r8180_priv *priv = ieee80211_priv(dev);
-
- down(&priv->wx_sem);
- if (priv->up)
- ret = ieee80211_wx_get_scan(priv->ieee80211, a, wrqu, b);
- else
- ret = -1;
-
- up(&priv->wx_sem);
- return ret;
-}
-
-
-static int r8180_wx_set_essid(struct net_device *dev,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *b)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
-
- int ret;
-
- if (priv->ieee80211->bHwRadioOff)
- return 0;
-
- down(&priv->wx_sem);
- if (priv->bInactivePs)
- IPSLeave(dev);
-
- ret = ieee80211_wx_set_essid(priv->ieee80211, a, wrqu, b);
-
- up(&priv->wx_sem);
- return ret;
-}
-
-
-static int r8180_wx_get_essid(struct net_device *dev,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *b)
-{
- int ret;
- struct r8180_priv *priv = ieee80211_priv(dev);
-
- down(&priv->wx_sem);
-
- ret = ieee80211_wx_get_essid(priv->ieee80211, a, wrqu, b);
-
- up(&priv->wx_sem);
-
- return ret;
-}
-
-
-static int r8180_wx_set_freq(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *b)
-{
- int ret;
- struct r8180_priv *priv = ieee80211_priv(dev);
-
-
- if (priv->ieee80211->bHwRadioOff)
- return 0;
-
- down(&priv->wx_sem);
-
- ret = ieee80211_wx_set_freq(priv->ieee80211, a, wrqu, b);
-
- up(&priv->wx_sem);
- return ret;
-}
-
-
-static int r8180_wx_get_name(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- return ieee80211_wx_get_name(priv->ieee80211, info, wrqu, extra);
-}
-
-static int r8180_wx_set_frag(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
-
- if (priv->ieee80211->bHwRadioOff)
- return 0;
-
- if (wrqu->frag.disabled)
- priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
- else {
- if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
- wrqu->frag.value > MAX_FRAG_THRESHOLD)
- return -EINVAL;
-
- priv->ieee80211->fts = wrqu->frag.value & ~0x1;
- }
-
- return 0;
-}
-
-
-static int r8180_wx_get_frag(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
-
- wrqu->frag.value = priv->ieee80211->fts;
- wrqu->frag.fixed = 0; /* no auto select */
- wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD);
-
- return 0;
-}
-
-
-static int r8180_wx_set_wap(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *awrq, char *extra)
-{
- int ret;
- struct r8180_priv *priv = ieee80211_priv(dev);
-
- if (priv->ieee80211->bHwRadioOff)
- return 0;
-
- down(&priv->wx_sem);
-
- ret = ieee80211_wx_set_wap(priv->ieee80211, info, awrq, extra);
-
- up(&priv->wx_sem);
- return ret;
-
-}
-
-
-static int r8180_wx_get_wap(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
-
- return ieee80211_wx_get_wap(priv->ieee80211, info, wrqu, extra);
-}
-
-
-static int r8180_wx_set_enc(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *key)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- int ret;
-
- if (priv->ieee80211->bHwRadioOff)
- return 0;
-
-
- down(&priv->wx_sem);
-
- if (priv->hw_wep)
- ret = r8180_wx_set_key(dev, info, wrqu, key);
- else {
- DMESG("Setting SW wep key");
- ret = ieee80211_wx_set_encode(priv->ieee80211, info, wrqu, key);
- }
-
- up(&priv->wx_sem);
- return ret;
-}
-
-
-static int r8180_wx_get_enc(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *key)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
-
- return ieee80211_wx_get_encode(priv->ieee80211, info, wrqu, key);
-}
-
-
-static int r8180_wx_set_scan_type(struct net_device *dev,
- struct iw_request_info *aa,
- union iwreq_data *wrqu, char *p)
-{
-
- struct r8180_priv *priv = ieee80211_priv(dev);
- int *parms = (int *)p;
- int mode = parms[0];
-
- if (priv->ieee80211->bHwRadioOff)
- return 0;
-
- priv->ieee80211->active_scan = mode;
-
- return 1;
-}
-
-static int r8180_wx_set_retry(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- int err = 0;
-
- if (priv->ieee80211->bHwRadioOff)
- return 0;
-
- down(&priv->wx_sem);
-
- if (wrqu->retry.flags & IW_RETRY_LIFETIME ||
- wrqu->retry.disabled) {
- err = -EINVAL;
- goto exit;
- }
- if (!(wrqu->retry.flags & IW_RETRY_LIMIT)) {
- err = -EINVAL;
- goto exit;
- }
-
- if (wrqu->retry.value > R8180_MAX_RETRY) {
- err = -EINVAL;
- goto exit;
- }
- if (wrqu->retry.flags & IW_RETRY_MAX) {
- priv->retry_rts = wrqu->retry.value;
- DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value);
-
- } else {
- priv->retry_data = wrqu->retry.value;
- DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value);
- }
-
- /* FIXME !
- * We might try to write directly the TX config register
- * or to restart just the (R)TX process.
- * I'm unsure if whole reset is really needed
- */
-
- rtl8180_commit(dev);
-exit:
- up(&priv->wx_sem);
-
- return err;
-}
-
-static int r8180_wx_get_retry(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
-
-
- wrqu->retry.disabled = 0; /* can't be disabled */
-
- if ((wrqu->retry.flags & IW_RETRY_TYPE) ==
- IW_RETRY_LIFETIME)
- return -EINVAL;
-
- if (wrqu->retry.flags & IW_RETRY_MAX) {
- wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
- wrqu->retry.value = priv->retry_rts;
- } else {
- wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN;
- wrqu->retry.value = priv->retry_data;
- }
-
- return 0;
-}
-
-static int r8180_wx_get_sens(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- if (priv->rf_set_sens == NULL)
- return -1; /* we have not this support for this radio */
- wrqu->sens.value = priv->sens;
- return 0;
-}
-
-
-static int r8180_wx_set_sens(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-
- struct r8180_priv *priv = ieee80211_priv(dev);
-
- short err = 0;
-
- if (priv->ieee80211->bHwRadioOff)
- return 0;
-
- down(&priv->wx_sem);
- if (priv->rf_set_sens == NULL) {
- err = -1; /* we have not this support for this radio */
- goto exit;
- }
- if (priv->rf_set_sens(dev, wrqu->sens.value) == 0)
- priv->sens = wrqu->sens.value;
- else
- err = -EINVAL;
-
-exit:
- up(&priv->wx_sem);
-
- return err;
-}
-
-
-static int r8180_wx_set_rawtx(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- int ret;
-
- if (priv->ieee80211->bHwRadioOff)
- return 0;
-
- down(&priv->wx_sem);
-
- ret = ieee80211_wx_set_rawtx(priv->ieee80211, info, wrqu, extra);
-
- up(&priv->wx_sem);
-
- return ret;
-
-}
-
-static int r8180_wx_get_power(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- int ret;
- struct r8180_priv *priv = ieee80211_priv(dev);
-
- down(&priv->wx_sem);
-
- ret = ieee80211_wx_get_power(priv->ieee80211, info, wrqu, extra);
-
- up(&priv->wx_sem);
-
- return ret;
-}
-
-static int r8180_wx_set_power(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- int ret;
- struct r8180_priv *priv = ieee80211_priv(dev);
-
-
- if (priv->ieee80211->bHwRadioOff)
- return 0;
-
- down(&priv->wx_sem);
- printk("=>>>>>>>>>>=============================>set power:%d, %d!\n", wrqu->power.disabled, wrqu->power.flags);
- if (wrqu->power.disabled == 0) {
- wrqu->power.flags |= IW_POWER_ALL_R;
- wrqu->power.flags |= IW_POWER_TIMEOUT;
- wrqu->power.value = 1000;
- }
-
- ret = ieee80211_wx_set_power(priv->ieee80211, info, wrqu, extra);
-
- up(&priv->wx_sem);
-
- return ret;
-}
-
-static int r8180_wx_set_rts(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
-
-
- if (priv->ieee80211->bHwRadioOff)
- return 0;
-
- if (wrqu->rts.disabled)
- priv->rts = DEFAULT_RTS_THRESHOLD;
- else {
- if (wrqu->rts.value < MIN_RTS_THRESHOLD ||
- wrqu->rts.value > MAX_RTS_THRESHOLD)
- return -EINVAL;
-
- priv->rts = wrqu->rts.value;
- }
-
- return 0;
-}
-static int r8180_wx_get_rts(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
-
-
-
- wrqu->rts.value = priv->rts;
- wrqu->rts.fixed = 0; /* no auto select */
- wrqu->rts.disabled = (wrqu->rts.value == 0);
-
- return 0;
-}
-static int dummy(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *b)
-{
- return -1;
-}
-
-static int r8180_wx_get_iwmode(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- struct ieee80211_device *ieee;
- int ret = 0;
-
-
-
- down(&priv->wx_sem);
-
- ieee = priv->ieee80211;
-
- strcpy(extra, "802.11");
- if (ieee->modulation & IEEE80211_CCK_MODULATION) {
- strcat(extra, "b");
- if (ieee->modulation & IEEE80211_OFDM_MODULATION)
- strcat(extra, "/g");
- } else if (ieee->modulation & IEEE80211_OFDM_MODULATION)
- strcat(extra, "g");
-
- up(&priv->wx_sem);
-
- return ret;
-}
-static int r8180_wx_set_iwmode(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- struct ieee80211_device *ieee = priv->ieee80211;
- int *param = (int *)extra;
- int ret = 0;
- int modulation = 0, mode = 0;
-
-
- if (priv->ieee80211->bHwRadioOff)
- return 0;
-
- down(&priv->wx_sem);
-
- if (*param == 1) {
- modulation |= IEEE80211_CCK_MODULATION;
- mode = IEEE_B;
- printk(KERN_INFO "B mode!\n");
- } else if (*param == 2) {
- modulation |= IEEE80211_OFDM_MODULATION;
- mode = IEEE_G;
- printk(KERN_INFO "G mode!\n");
- } else if (*param == 3) {
- modulation |= IEEE80211_CCK_MODULATION;
- modulation |= IEEE80211_OFDM_MODULATION;
- mode = IEEE_B|IEEE_G;
- printk(KERN_INFO "B/G mode!\n");
- }
-
- if (ieee->proto_started) {
- ieee80211_stop_protocol(ieee);
- ieee->mode = mode;
- ieee->modulation = modulation;
- ieee80211_start_protocol(ieee);
- } else {
- ieee->mode = mode;
- ieee->modulation = modulation;
- }
-
- up(&priv->wx_sem);
-
- return ret;
-}
-static int r8180_wx_get_preamble(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
-
-
-
- down(&priv->wx_sem);
-
-
-
- *extra = (char) priv->plcp_preamble_mode; /* 0:auto 1:short 2:long */
- up(&priv->wx_sem);
-
- return 0;
-}
-static int r8180_wx_set_preamble(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- int ret = 0;
-
-
- if (priv->ieee80211->bHwRadioOff)
- return 0;
-
- down(&priv->wx_sem);
- if (*extra < 0 || *extra > 2)
- ret = -1;
- else
- priv->plcp_preamble_mode = *((short *)extra);
-
-
-
- up(&priv->wx_sem);
-
- return ret;
-}
-static int r8180_wx_get_siglevel(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- int ret = 0;
-
-
-
- down(&priv->wx_sem);
- /* Modify by hikaru 6.5 */
- *((int *)extra) = priv->wstats.qual.level;/*for interface test ,it should be the priv->wstats.qual.level; */
-
-
-
- up(&priv->wx_sem);
-
- return ret;
-}
-static int r8180_wx_get_sigqual(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- int ret = 0;
-
-
-
- down(&priv->wx_sem);
- /* Modify by hikaru 6.5 */
- *((int *)extra) = priv->wstats.qual.qual;/* for interface test ,it should be the priv->wstats.qual.qual; */
-
-
-
- up(&priv->wx_sem);
-
- return ret;
-}
-static int r8180_wx_reset_stats(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- down(&priv->wx_sem);
-
- priv->stats.txrdu = 0;
- priv->stats.rxrdu = 0;
- priv->stats.rxnolast = 0;
- priv->stats.rxnodata = 0;
- priv->stats.rxnopointer = 0;
- priv->stats.txnperr = 0;
- priv->stats.txresumed = 0;
- priv->stats.rxerr = 0;
- priv->stats.rxoverflow = 0;
- priv->stats.rxint = 0;
-
- priv->stats.txnpokint = 0;
- priv->stats.txhpokint = 0;
- priv->stats.txhperr = 0;
- priv->stats.ints = 0;
- priv->stats.shints = 0;
- priv->stats.txoverflow = 0;
- priv->stats.rxdmafail = 0;
- priv->stats.txbeacon = 0;
- priv->stats.txbeaconerr = 0;
- priv->stats.txlpokint = 0;
- priv->stats.txlperr = 0;
- priv->stats.txretry = 0;/* 20060601 */
- priv->stats.rxcrcerrmin = 0 ;
- priv->stats.rxcrcerrmid = 0;
- priv->stats.rxcrcerrmax = 0;
- priv->stats.rxicverr = 0;
-
- up(&priv->wx_sem);
-
- return 0;
-
-}
-static int r8180_wx_radio_on(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
-
- if (priv->ieee80211->bHwRadioOff)
- return 0;
-
-
- down(&priv->wx_sem);
- priv->rf_wakeup(dev);
-
- up(&priv->wx_sem);
-
- return 0;
-
-}
-
-static int r8180_wx_radio_off(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
-
- if (priv->ieee80211->bHwRadioOff)
- return 0;
-
-
- down(&priv->wx_sem);
- priv->rf_sleep(dev);
-
- up(&priv->wx_sem);
-
- return 0;
-
-}
-static int r8180_wx_get_channelplan(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
-
-
-
- down(&priv->wx_sem);
- *extra = priv->channel_plan;
-
-
-
- up(&priv->wx_sem);
-
- return 0;
-}
-static int r8180_wx_set_channelplan(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- int *val = (int *)extra;
- int i;
- printk("-----in fun %s\n", __func__);
-
- if (priv->ieee80211->bHwRadioOff)
- return 0;
-
- /* unsigned long flags; */
- down(&priv->wx_sem);
- if (default_channel_plan[*val].len != 0) {
- priv->channel_plan = *val;
- /* Clear old channel map 8 */
- for (i = 1; i <= MAX_CHANNEL_NUMBER; i++)
- GET_DOT11D_INFO(priv->ieee80211)->channel_map[i] = 0;
-
- /* Set new channel map */
- for (i = 1; i <= default_channel_plan[*val].len; i++)
- GET_DOT11D_INFO(priv->ieee80211)->channel_map[default_channel_plan[*val].channel[i-1]] = 1;
-
- }
- up(&priv->wx_sem);
-
- return 0;
-}
-
-static int r8180_wx_get_version(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- /* struct ieee80211_device *ieee; */
-
- down(&priv->wx_sem);
- strcpy(extra, "1020.0808");
- up(&priv->wx_sem);
-
- return 0;
-}
-
-/* added by amy 080818 */
-/*receive datarate from user typing valid rate is from 2 to 108 (1 - 54M), if input 0, return to normal rate adaptive. */
-static int r8180_wx_set_forcerate(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- u8 forcerate = *extra;
-
- down(&priv->wx_sem);
-
- printk("==============>%s(): forcerate is %d\n", __func__, forcerate);
- if ((forcerate == 2) || (forcerate == 4) || (forcerate == 11) || (forcerate == 22) || (forcerate == 12) ||
- (forcerate == 18) || (forcerate == 24) || (forcerate == 36) || (forcerate == 48) || (forcerate == 72) ||
- (forcerate == 96) || (forcerate == 108)) {
- priv->ForcedDataRate = 1;
- priv->ieee80211->rate = forcerate * 5;
- } else if (forcerate == 0) {
- priv->ForcedDataRate = 0;
- printk("OK! return rate adaptive\n");
- } else
- printk("ERR: wrong rate\n");
- up(&priv->wx_sem);
- return 0;
-}
-
-static int r8180_wx_set_enc_ext(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
-
- struct r8180_priv *priv = ieee80211_priv(dev);
-
- int ret = 0;
-
- if (priv->ieee80211->bHwRadioOff)
- return 0;
-
- down(&priv->wx_sem);
- ret = ieee80211_wx_set_encode_ext(priv->ieee80211, info, wrqu, extra);
- up(&priv->wx_sem);
- return ret;
-
-}
-static int r8180_wx_set_auth(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- int ret = 0;
-
- if (priv->ieee80211->bHwRadioOff)
- return 0;
-
- down(&priv->wx_sem);
- ret = ieee80211_wx_set_auth(priv->ieee80211, info, &wrqu->param, extra);
- up(&priv->wx_sem);
- return ret;
-}
-
-static int r8180_wx_set_mlme(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- int ret = 0;
- struct r8180_priv *priv = ieee80211_priv(dev);
-
-
- if (priv->ieee80211->bHwRadioOff)
- return 0;
-
-
- down(&priv->wx_sem);
-#if 1
- ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra);
-#endif
- up(&priv->wx_sem);
- return ret;
-}
-static int r8180_wx_set_gen_ie(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- int ret = 0;
- struct r8180_priv *priv = ieee80211_priv(dev);
-
-
- if (priv->ieee80211->bHwRadioOff)
- return 0;
-
- down(&priv->wx_sem);
-#if 1
- ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, wrqu->data.length);
-#endif
- up(&priv->wx_sem);
- return ret;
-
-
-}
-
-static const iw_handler r8180_wx_handlers[] = {
- IW_HANDLER(SIOCGIWNAME, r8180_wx_get_name),
- IW_HANDLER(SIOCSIWNWID, dummy),
- IW_HANDLER(SIOCGIWNWID, dummy),
- IW_HANDLER(SIOCSIWFREQ, r8180_wx_set_freq),
- IW_HANDLER(SIOCGIWFREQ, r8180_wx_get_freq),
- IW_HANDLER(SIOCSIWMODE, r8180_wx_set_mode),
- IW_HANDLER(SIOCGIWMODE, r8180_wx_get_mode),
- IW_HANDLER(SIOCSIWSENS, r8180_wx_set_sens),
- IW_HANDLER(SIOCGIWSENS, r8180_wx_get_sens),
- IW_HANDLER(SIOCGIWRANGE, rtl8180_wx_get_range),
- IW_HANDLER(SIOCSIWSPY, dummy),
- IW_HANDLER(SIOCGIWSPY, dummy),
- IW_HANDLER(SIOCSIWAP, r8180_wx_set_wap),
- IW_HANDLER(SIOCGIWAP, r8180_wx_get_wap),
- IW_HANDLER(SIOCSIWMLME, r8180_wx_set_mlme),
- IW_HANDLER(SIOCGIWAPLIST, dummy), /* deprecated */
- IW_HANDLER(SIOCSIWSCAN, r8180_wx_set_scan),
- IW_HANDLER(SIOCGIWSCAN, r8180_wx_get_scan),
- IW_HANDLER(SIOCSIWESSID, r8180_wx_set_essid),
- IW_HANDLER(SIOCGIWESSID, r8180_wx_get_essid),
- IW_HANDLER(SIOCSIWNICKN, dummy),
- IW_HANDLER(SIOCGIWNICKN, dummy),
- IW_HANDLER(SIOCSIWRATE, r8180_wx_set_rate),
- IW_HANDLER(SIOCGIWRATE, r8180_wx_get_rate),
- IW_HANDLER(SIOCSIWRTS, r8180_wx_set_rts),
- IW_HANDLER(SIOCGIWRTS, r8180_wx_get_rts),
- IW_HANDLER(SIOCSIWFRAG, r8180_wx_set_frag),
- IW_HANDLER(SIOCGIWFRAG, r8180_wx_get_frag),
- IW_HANDLER(SIOCSIWTXPOW, dummy),
- IW_HANDLER(SIOCGIWTXPOW, dummy),
- IW_HANDLER(SIOCSIWRETRY, r8180_wx_set_retry),
- IW_HANDLER(SIOCGIWRETRY, r8180_wx_get_retry),
- IW_HANDLER(SIOCSIWENCODE, r8180_wx_set_enc),
- IW_HANDLER(SIOCGIWENCODE, r8180_wx_get_enc),
- IW_HANDLER(SIOCSIWPOWER, r8180_wx_set_power),
- IW_HANDLER(SIOCGIWPOWER, r8180_wx_get_power),
- IW_HANDLER(SIOCSIWGENIE, r8180_wx_set_gen_ie),
- IW_HANDLER(SIOCSIWAUTH, r8180_wx_set_auth),
- IW_HANDLER(SIOCSIWENCODEEXT, r8180_wx_set_enc_ext),
-};
-
-static const struct iw_priv_args r8180_private_args[] = {
- {
- SIOCIWFIRSTPRIV + 0x0,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "badcrc"
- },
- { SIOCIWFIRSTPRIV + 0x1,
- 0, 0, "dummy"
-
- },
- {
- SIOCIWFIRSTPRIV + 0x2,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "beaconint"
- },
- { SIOCIWFIRSTPRIV + 0x3,
- 0, 0, "dummy"
-
- },
- {
- SIOCIWFIRSTPRIV + 0x4,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan"
-
- },
- { SIOCIWFIRSTPRIV + 0x5,
- 0, 0, "dummy"
-
- },
- {
- SIOCIWFIRSTPRIV + 0x6,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx"
-
- },
- { SIOCIWFIRSTPRIV + 0x7,
- 0, 0, "dummy"
-
- },
- {
- SIOCIWFIRSTPRIV + 0x8,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setiwmode"
- },
- {
- SIOCIWFIRSTPRIV + 0x9,
- 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 32, "getiwmode"
- },
- {
- SIOCIWFIRSTPRIV + 0xA,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setpreamble"
- },
- {
- SIOCIWFIRSTPRIV + 0xB,
- 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getpreamble"
- },
- { SIOCIWFIRSTPRIV + 0xC,
- 0, 0, "dummy"
- },
- {
- SIOCIWFIRSTPRIV + 0xD,
- 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getrssi"
- },
- { SIOCIWFIRSTPRIV + 0xE,
- 0, 0, "dummy"
- },
- {
- SIOCIWFIRSTPRIV + 0xF,
- 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getlinkqual"
- },
- {
- SIOCIWFIRSTPRIV + 0x10,
- 0, 0, "resetstats"
- },
- {
- SIOCIWFIRSTPRIV + 0x11,
- 0, 0, "dummy"
- },
- {
- SIOCIWFIRSTPRIV + 0x12,
- 0, 0, "radioon"
- },
- {
- SIOCIWFIRSTPRIV + 0x13,
- 0, 0, "radiooff"
- },
- {
- SIOCIWFIRSTPRIV + 0x14,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setchannel"
- },
- {
- SIOCIWFIRSTPRIV + 0x15,
- 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getchannel"
- },
- {
- SIOCIWFIRSTPRIV + 0x16,
- 0, 0, "dummy"
- },
- {
- SIOCIWFIRSTPRIV + 0x17,
- 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 32, "getversion"
- },
- {
- SIOCIWFIRSTPRIV + 0x18,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setrate"
- },
-};
-
-
-static iw_handler r8180_private_handler[] = {
- r8180_wx_set_crcmon, /*SIOCIWSECONDPRIV*/
- dummy,
- r8180_wx_set_beaconinterval,
- dummy,
- /* r8180_wx_set_monitor_type, */
- r8180_wx_set_scan_type,
- dummy,
- r8180_wx_set_rawtx,
- dummy,
- r8180_wx_set_iwmode,
- r8180_wx_get_iwmode,
- r8180_wx_set_preamble,
- r8180_wx_get_preamble,
- dummy,
- r8180_wx_get_siglevel,
- dummy,
- r8180_wx_get_sigqual,
- r8180_wx_reset_stats,
- dummy,/* r8180_wx_get_stats */
- r8180_wx_radio_on,
- r8180_wx_radio_off,
- r8180_wx_set_channelplan,
- r8180_wx_get_channelplan,
- dummy,
- r8180_wx_get_version,
- r8180_wx_set_forcerate,
-};
-
-static inline int is_same_network(struct ieee80211_network *src,
- struct ieee80211_network *dst,
- struct ieee80211_device *ieee)
-{
- /* A network is only a duplicate if the channel, BSSID, ESSID
- * and the capability field (in particular IBSS and BSS) all match.
- * We treat all <hidden> with the same BSSID and channel
- * as one network
- */
- if (src->channel != dst->channel)
- return 0;
-
- if (memcmp(src->bssid, dst->bssid, ETH_ALEN) != 0)
- return 0;
-
- if (ieee->iw_mode != IW_MODE_INFRA) {
- if (src->ssid_len != dst->ssid_len)
- return 0;
- if (memcmp(src->ssid, dst->ssid, src->ssid_len) != 0)
- return 0;
- }
-
- if ((src->capability & WLAN_CAPABILITY_IBSS) !=
- (dst->capability & WLAN_CAPABILITY_IBSS))
- return 0;
- if ((src->capability & WLAN_CAPABILITY_BSS) !=
- (dst->capability & WLAN_CAPABILITY_BSS))
- return 0;
-
- return 1;
-}
-
-/* WB modified to show signal to GUI on 18-01-2008 */
-static struct iw_statistics *r8180_get_wireless_stats(struct net_device *dev)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- struct ieee80211_device *ieee = priv->ieee80211;
- struct iw_statistics *wstats = &priv->wstats;
- int tmp_level = 0;
- int tmp_qual = 0;
- int tmp_noise = 0;
-
- if (ieee->state < IEEE80211_LINKED) {
- wstats->qual.qual = 0;
- wstats->qual.level = 0;
- wstats->qual.noise = 0;
- wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
- return wstats;
- }
-
- tmp_level = (&ieee->current_network)->stats.signal;
- tmp_qual = (&ieee->current_network)->stats.signalstrength;
- tmp_noise = (&ieee->current_network)->stats.noise;
-
- wstats->qual.level = tmp_level;
- wstats->qual.qual = tmp_qual;
- wstats->qual.noise = tmp_noise;
- wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
- return wstats;
-}
-
-struct iw_handler_def r8180_wx_handlers_def = {
- .standard = r8180_wx_handlers,
- .num_standard = ARRAY_SIZE(r8180_wx_handlers),
- .private = r8180_private_handler,
- .num_private = ARRAY_SIZE(r8180_private_handler),
- .num_private_args = sizeof(r8180_private_args) / sizeof(struct iw_priv_args),
- .get_wireless_stats = r8180_get_wireless_stats,
- .private_args = (struct iw_priv_args *)r8180_private_args,
-};
-
-
diff --git a/drivers/staging/rtl8187se/r8180_wx.h b/drivers/staging/rtl8187se/r8180_wx.h
deleted file mode 100644
index d471520ac772..000000000000
--- a/drivers/staging/rtl8187se/r8180_wx.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- This is part of rtl8180 OpenSource driver - v 0.3
- Copyright (C) Andrea Merello 2004 <andrea.merello@gmail.com>
- Released under the terms of GPL (General Public Licence)
-
- Parts of this driver are based on the GPL part of the official realtek driver
- Parts of this driver are based on the rtl8180 driver skeleton from Patric Schenke & Andres Salomon
- Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver
-
- We want to thanks the Authors of such projects and the Ndiswrapper project Authors.
-*/
-
-/* this file (will) contains wireless extension handlers*/
-
-#ifndef R8180_WX_H
-#define R8180_WX_H
-#include <linux/wireless.h>
-#include "ieee80211/ieee80211.h"
-extern struct iw_handler_def r8180_wx_handlers_def;
-
-#endif
diff --git a/drivers/staging/rtl8187se/r8185b_init.c b/drivers/staging/rtl8187se/r8185b_init.c
deleted file mode 100644
index cc6f100814f3..000000000000
--- a/drivers/staging/rtl8187se/r8185b_init.c
+++ /dev/null
@@ -1,1464 +0,0 @@
-/*
- * Copyright (c) Realtek Semiconductor Corp. All rights reserved.
- *
- * Module Name:
- * r8185b_init.c
- *
- * Abstract:
- * Hardware Initialization and Hardware IO for RTL8185B
- *
- * Major Change History:
- * When Who What
- * ---------- --------------- -------------------------------
- * 2006-11-15 Xiong Created
- *
- * Notes:
- * This file is ported from RTL8185B Windows driver.
- *
- *
- */
-
-/*--------------------------Include File------------------------------------*/
-#include <linux/spinlock.h>
-#include "r8180_hw.h"
-#include "r8180.h"
-#include "r8180_rtl8225.h" /* RTL8225 Radio frontend */
-#include "r8180_93cx6.h" /* Card EEPROM */
-#include "r8180_wx.h"
-#include "ieee80211/dot11d.h"
-/* #define CONFIG_RTL8180_IO_MAP */
-#define TC_3W_POLL_MAX_TRY_CNT 5
-
-static u8 MAC_REG_TABLE[][2] = {
- /*
- * PAGE 0:
- * 0x34(BRSR), 0xBE(RATE_FALLBACK_CTL), 0x1E0(ARFR) would set in
- * HwConfigureRTL8185()
- * 0x272(RFSW_CTRL), 0x1CE(AESMSK_QC) set in InitializeAdapter8185().
- * 0x1F0~0x1F8 set in MacConfig_85BASIC()
- */
- {0x08, 0xae}, {0x0a, 0x72}, {0x5b, 0x42},
- {0x84, 0x88}, {0x85, 0x24}, {0x88, 0x54}, {0x8b, 0xb8}, {0x8c, 0x03},
- {0x8d, 0x40}, {0x8e, 0x00}, {0x8f, 0x00}, {0x5b, 0x18}, {0x91, 0x03},
- {0x94, 0x0F}, {0x95, 0x32},
- {0x96, 0x00}, {0x97, 0x07}, {0xb4, 0x22}, {0xdb, 0x00},
- {0xf0, 0x32}, {0xf1, 0x32}, {0xf2, 0x00}, {0xf3, 0x00}, {0xf4, 0x32},
- {0xf5, 0x43}, {0xf6, 0x00}, {0xf7, 0x00}, {0xf8, 0x46}, {0xf9, 0xa4},
- {0xfa, 0x00}, {0xfb, 0x00}, {0xfc, 0x96}, {0xfd, 0xa4}, {0xfe, 0x00},
- {0xff, 0x00},
-
- /*
- * PAGE 1:
- * For Flextronics system Logo PCIHCT failure:
- * 0x1C4~0x1CD set no-zero value to avoid PCI configuration
- * space 0x45[7]=1
- */
- {0x5e, 0x01},
- {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x04}, {0x5b, 0x00}, {0x60, 0x24},
- {0x61, 0x97}, {0x62, 0xF0}, {0x63, 0x09}, {0x80, 0x0F}, {0x81, 0xFF},
- {0x82, 0xFF}, {0x83, 0x03},
- /* lzm add 080826 */
- {0xC4, 0x22}, {0xC5, 0x22}, {0xC6, 0x22}, {0xC7, 0x22}, {0xC8, 0x22},
- /* lzm add 080826 */
- {0xC9, 0x22}, {0xCA, 0x22}, {0xCB, 0x22}, {0xCC, 0x22}, {0xCD, 0x22},
- {0xe2, 0x00},
-
-
- /* PAGE 2: */
- {0x5e, 0x02},
- {0x0c, 0x04}, {0x4c, 0x30}, {0x4d, 0x08}, {0x50, 0x05}, {0x51, 0xf5},
- {0x52, 0x04}, {0x53, 0xa0}, {0x54, 0xff}, {0x55, 0xff}, {0x56, 0xff},
- {0x57, 0xff}, {0x58, 0x08}, {0x59, 0x08}, {0x5a, 0x08}, {0x5b, 0x08},
- {0x60, 0x08}, {0x61, 0x08}, {0x62, 0x08}, {0x63, 0x08}, {0x64, 0x2f},
- {0x8c, 0x3f}, {0x8d, 0x3f}, {0x8e, 0x3f},
- {0x8f, 0x3f}, {0xc4, 0xff}, {0xc5, 0xff}, {0xc6, 0xff}, {0xc7, 0xff},
- {0xc8, 0x00}, {0xc9, 0x00}, {0xca, 0x80}, {0xcb, 0x00},
-
- /* PAGE 0: */
- {0x5e, 0x00}, {0x9f, 0x03}
- };
-
-
-static u8 ZEBRA_AGC[] = {
- 0,
- 0x7E, 0x7E, 0x7E, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, 0x79, 0x78, 0x77, 0x76,
- 0x75, 0x74, 0x73, 0x72, 0x71, 0x70, 0x6F, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A,
- 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0x48, 0x47, 0x46, 0x45,
- 0x44, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x08, 0x07,
- 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
- 0x0f, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x15, 0x16, 0x17, 0x17, 0x18, 0x18,
- 0x19, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1e, 0x1e,
- 0x1f, 0x1f, 0x1f, 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21, 0x22, 0x22,
- 0x22, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
- 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F
- };
-
-static u32 ZEBRA_RF_RX_GAIN_TABLE[] = {
- 0x0096, 0x0076, 0x0056, 0x0036, 0x0016, 0x01f6, 0x01d6, 0x01b6,
- 0x0196, 0x0176, 0x00F7, 0x00D7, 0x00B7, 0x0097, 0x0077, 0x0057,
- 0x0037, 0x00FB, 0x00DB, 0x00BB, 0x00FF, 0x00E3, 0x00C3, 0x00A3,
- 0x0083, 0x0063, 0x0043, 0x0023, 0x0003, 0x01E3, 0x01C3, 0x01A3,
- 0x0183, 0x0163, 0x0143, 0x0123, 0x0103
- };
-
-static u8 OFDM_CONFIG[] = {
- /* OFDM reg0x06[7:0]=0xFF: Enable power saving mode in RX */
- /* OFDM reg0x3C[4]=1'b1: Enable RX power saving mode */
- /* ofdm 0x3a = 0x7b ,(original : 0xfb) For ECS shielding room TP test */
- /* 0x00 */
- 0x10, 0x0F, 0x0A, 0x0C, 0x14, 0xFA, 0xFF, 0x50,
- 0x00, 0x50, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00,
- /* 0x10 */
- 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xA8, 0x26,
- 0x32, 0x33, 0x06, 0xA5, 0x6F, 0x55, 0xC8, 0xBB,
- /* 0x20 */
- 0x0A, 0xE1, 0x2C, 0x4A, 0x86, 0x83, 0x34, 0x00,
- 0x4F, 0x24, 0x6F, 0xC2, 0x03, 0x40, 0x80, 0x00,
- /* 0x30 */
- 0xC0, 0xC1, 0x58, 0xF1, 0x00, 0xC4, 0x90, 0x3e,
- 0xD8, 0x3C, 0x7B, 0x10, 0x10
- };
-
- /*---------------------------------------------------------------
- * Hardware IO
- * the code is ported from Windows source code
- *---------------------------------------------------------------
- */
-
-static u8 PlatformIORead1Byte(struct net_device *dev, u32 offset)
-{
- return read_nic_byte(dev, offset);
-}
-
-static void PlatformIOWrite1Byte(struct net_device *dev, u32 offset, u8 data)
-{
- write_nic_byte(dev, offset, data);
- /*
- * To make sure write operation is completed,
- * 2005.11.09, by rcnjko.
- */
- read_nic_byte(dev, offset);
-}
-
-static void PlatformIOWrite2Byte(struct net_device *dev, u32 offset, u16 data)
-{
- write_nic_word(dev, offset, data);
- /*
- * To make sure write operation is completed,
- * 2005.11.09, by rcnjko.
- */
- read_nic_word(dev, offset);
-}
-
-static void PlatformIOWrite4Byte(struct net_device *dev, u32 offset, u32 data)
-{
- if (offset == PhyAddr) {
- /* For Base Band configuration. */
- unsigned char cmdByte;
- unsigned long dataBytes;
- unsigned char idx;
- u8 u1bTmp;
-
- cmdByte = (u8)(data & 0x000000ff);
- dataBytes = data>>8;
-
- /*
- * 071010, rcnjko:
- * The critical section is only BB read/write race
- * condition. Assumption:
- * 1. We assume NO one will access BB at DIRQL, otherwise,
- * system will crash for
- * acquiring the spinlock in such context.
- * 2. PlatformIOWrite4Byte() MUST NOT be recursive.
- */
- /* NdisAcquireSpinLock( &(pDevice->IoSpinLock) ); */
-
- for (idx = 0; idx < 30; idx++) {
- /* Make sure command bit is clear before access it. */
- u1bTmp = PlatformIORead1Byte(dev, PhyAddr);
- if ((u1bTmp & BIT7) == 0)
- break;
- else
- mdelay(10);
- }
-
- for (idx = 0; idx < 3; idx++)
- PlatformIOWrite1Byte(dev, offset+1+idx,
- ((u8 *)&dataBytes)[idx]);
-
- write_nic_byte(dev, offset, cmdByte);
-
- /* NdisReleaseSpinLock( &(pDevice->IoSpinLock) ); */
- } else {
- write_nic_dword(dev, offset, data);
- /*
- * To make sure write operation is completed, 2005.11.09,
- * by rcnjko.
- */
- read_nic_dword(dev, offset);
- }
-}
-
-static void SetOutputEnableOfRfPins(struct net_device *dev)
-{
- write_nic_word(dev, RFPinsEnable, 0x1bff);
-}
-
-static bool HwHSSIThreeWire(struct net_device *dev,
- u8 *pDataBuf,
- bool write)
-{
- u8 TryCnt;
- u8 u1bTmp;
-
- /* Check if WE and RE are cleared. */
- for (TryCnt = 0; TryCnt < TC_3W_POLL_MAX_TRY_CNT; TryCnt++) {
- u1bTmp = read_nic_byte(dev, SW_3W_CMD1);
- if ((u1bTmp & (SW_3W_CMD1_RE|SW_3W_CMD1_WE)) == 0)
- break;
-
- udelay(10);
- }
- if (TryCnt == TC_3W_POLL_MAX_TRY_CNT) {
- netdev_err(dev,
- "HwThreeWire(): CmdReg: %#X RE|WE bits are not clear!!\n",
- u1bTmp);
- return false;
- }
-
- /* RTL8187S HSSI Read/Write Function */
- u1bTmp = read_nic_byte(dev, RF_SW_CONFIG);
- u1bTmp |= RF_SW_CFG_SI; /* reg08[1]=1 Serial Interface(SI) */
- write_nic_byte(dev, RF_SW_CONFIG, u1bTmp);
-
- /* jong: HW SI read must set reg84[3]=0. */
- u1bTmp = read_nic_byte(dev, RFPinsSelect);
- u1bTmp &= ~BIT3;
- write_nic_byte(dev, RFPinsSelect, u1bTmp);
- /* Fill up data buffer for write operation. */
-
- /* SI - reg274[3:0] : RF register's Address */
- if (write)
- write_nic_word(dev, SW_3W_DB0, *((u16 *)pDataBuf));
- else
- write_nic_word(dev, SW_3W_DB0, *((u16 *)pDataBuf));
-
- /* Set up command: WE or RE. */
- if (write)
- write_nic_byte(dev, SW_3W_CMD1, SW_3W_CMD1_WE);
- else
- write_nic_byte(dev, SW_3W_CMD1, SW_3W_CMD1_RE);
-
-
- /* Check if DONE is set. */
- for (TryCnt = 0; TryCnt < TC_3W_POLL_MAX_TRY_CNT; TryCnt++) {
- u1bTmp = read_nic_byte(dev, SW_3W_CMD1);
- if (u1bTmp & SW_3W_CMD1_DONE)
- break;
-
- udelay(10);
- }
-
- write_nic_byte(dev, SW_3W_CMD1, 0);
-
- /* Read back data for read operation. */
- if (!write) {
- /* Serial Interface : reg363_362[11:0] */
- *((u16 *)pDataBuf) = read_nic_word(dev, SI_DATA_READ);
- *((u16 *)pDataBuf) &= 0x0FFF;
- }
-
- return true;
-}
-
-void RF_WriteReg(struct net_device *dev, u8 offset, u16 data)
-{
- u16 reg = (data << 4) | (offset & 0x0f);
- HwHSSIThreeWire(dev, (u8 *)&reg, true);
-}
-
-u16 RF_ReadReg(struct net_device *dev, u8 offset)
-{
- u16 reg = offset & 0x0f;
- HwHSSIThreeWire(dev, (u8 *)&reg, false);
- return reg;
-}
-
-static u8 ReadBBPortUchar(struct net_device *dev, u32 addr)
-{
- PlatformIOWrite4Byte(dev, PhyAddr, addr & 0xffffff7f);
- return PlatformIORead1Byte(dev, PhyDataR);
-}
-
-/* by Owen on 04/07/14 for writing BB register successfully */
-static void WriteBBPortUchar(struct net_device *dev, u32 Data)
-{
- PlatformIOWrite4Byte(dev, PhyAddr, Data);
- ReadBBPortUchar(dev, Data);
-}
-
-/*
- * Description:
- * Perform Antenna settings with antenna diversity on 87SE.
- * Created by Roger, 2008.01.25.
- */
-bool SetAntennaConfig87SE(struct net_device *dev,
- u8 DefaultAnt, /* 0: Main, 1: Aux. */
- bool bAntDiversity) /* 1:Enable, 0: Disable. */
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- bool bAntennaSwitched = true;
- /* 0x00 = disabled, 0x80 = enabled */
- u8 ant_diversity_offset = 0x00;
-
- /*
- * printk("SetAntennaConfig87SE(): DefaultAnt(%d), bAntDiversity(%d)\n",
- * DefaultAnt, bAntDiversity);
- */
-
- /* Threshold for antenna diversity. */
- write_phy_cck(dev, 0x0c, 0x09); /* Reg0c : 09 */
-
- if (bAntDiversity) /* Enable Antenna Diversity. */
- ant_diversity_offset = 0x80;
-
- if (DefaultAnt == 1) { /* aux Antenna */
- /* Mac register, aux antenna */
- write_nic_byte(dev, ANTSEL, 0x00);
-
- /* Config CCK RX antenna. */
- write_phy_cck(dev, 0x11, 0xbb); /* Reg11 : bb */
-
- /* Reg01 : 47 | ant_diversity_offset */
- write_phy_cck(dev, 0x01, 0x47|ant_diversity_offset);
-
- /* Config OFDM RX antenna. */
- write_phy_ofdm(dev, 0x0D, 0x54); /* Reg0d : 54 */
- /* Reg18 : 32 */
- write_phy_ofdm(dev, 0x18, 0x32|ant_diversity_offset);
- } else { /* main Antenna */
- /* Mac register, main antenna */
- write_nic_byte(dev, ANTSEL, 0x03);
-
- /* Config CCK RX antenna. */
- write_phy_cck(dev, 0x11, 0x9b); /* Reg11 : 9b */
- /* Reg01 : 47 */
- write_phy_cck(dev, 0x01, 0x47|ant_diversity_offset);
-
- /* Config OFDM RX antenna. */
- write_phy_ofdm(dev, 0x0D, 0x5c); /* Reg0d : 5c */
- /*Reg18 : 32 */
- write_phy_ofdm(dev, 0x18, 0x32|ant_diversity_offset);
- }
- priv->CurrAntennaIndex = DefaultAnt; /* Update default settings. */
- return bAntennaSwitched;
-}
-/*
- *--------------------------------------------------------------
- * Hardware Initialization.
- * the code is ported from Windows source code
- *--------------------------------------------------------------
- */
-
-static void ZEBRA_Config_85BASIC_HardCode(struct net_device *dev)
-{
-
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- u32 i;
- u32 addr, data;
- u32 u4bRegOffset, u4bRegValue;
- u16 u4bRF23, u4bRF24;
- u8 u1b24E;
- int d_cut = 0;
-
-
-/*
- *===========================================================================
- * 87S_PCIE :: RADIOCFG.TXT
- *===========================================================================
- */
-
-
- /* Page1 : reg16-reg30 */
- RF_WriteReg(dev, 0x00, 0x013f); mdelay(1); /* switch to page1 */
- u4bRF23 = RF_ReadReg(dev, 0x08); mdelay(1);
- u4bRF24 = RF_ReadReg(dev, 0x09); mdelay(1);
-
- if (u4bRF23 == 0x818 && u4bRF24 == 0x70C) {
- d_cut = 1;
- netdev_info(dev, "card type changed from C- to D-cut\n");
- }
-
- /* Page0 : reg0-reg15 */
-
- RF_WriteReg(dev, 0x00, 0x009f); mdelay(1);/* 1 */
- RF_WriteReg(dev, 0x01, 0x06e0); mdelay(1);
- RF_WriteReg(dev, 0x02, 0x004d); mdelay(1);/* 2 */
- RF_WriteReg(dev, 0x03, 0x07f1); mdelay(1);/* 3 */
- RF_WriteReg(dev, 0x04, 0x0975); mdelay(1);
- RF_WriteReg(dev, 0x05, 0x0c72); mdelay(1);
- RF_WriteReg(dev, 0x06, 0x0ae6); mdelay(1);
- RF_WriteReg(dev, 0x07, 0x00ca); mdelay(1);
- RF_WriteReg(dev, 0x08, 0x0e1c); mdelay(1);
- RF_WriteReg(dev, 0x09, 0x02f0); mdelay(1);
- RF_WriteReg(dev, 0x0a, 0x09d0); mdelay(1);
- RF_WriteReg(dev, 0x0b, 0x01ba); mdelay(1);
- RF_WriteReg(dev, 0x0c, 0x0640); mdelay(1);
- RF_WriteReg(dev, 0x0d, 0x08df); mdelay(1);
- RF_WriteReg(dev, 0x0e, 0x0020); mdelay(1);
- RF_WriteReg(dev, 0x0f, 0x0990); mdelay(1);
-
- /* Page1 : reg16-reg30 */
- RF_WriteReg(dev, 0x00, 0x013f); mdelay(1);
- RF_WriteReg(dev, 0x03, 0x0806); mdelay(1);
- RF_WriteReg(dev, 0x04, 0x03a7); mdelay(1);
- RF_WriteReg(dev, 0x05, 0x059b); mdelay(1);
- RF_WriteReg(dev, 0x06, 0x0081); mdelay(1);
- RF_WriteReg(dev, 0x07, 0x01A0); mdelay(1);
-/*
- * Don't write RF23/RF24 to make a difference between 87S C cut and D cut.
- * asked by SD3 stevenl.
- */
- RF_WriteReg(dev, 0x0a, 0x0001); mdelay(1);
- RF_WriteReg(dev, 0x0b, 0x0418); mdelay(1);
-
- if (d_cut) {
- RF_WriteReg(dev, 0x0c, 0x0fbe); mdelay(1);
- RF_WriteReg(dev, 0x0d, 0x0008); mdelay(1);
- /* RX LO buffer */
- RF_WriteReg(dev, 0x0e, 0x0807); mdelay(1);
- } else {
- RF_WriteReg(dev, 0x0c, 0x0fbe); mdelay(1);
- RF_WriteReg(dev, 0x0d, 0x0008); mdelay(1);
- /* RX LO buffer */
- RF_WriteReg(dev, 0x0e, 0x0806); mdelay(1);
- }
-
- RF_WriteReg(dev, 0x0f, 0x0acc); mdelay(1);
- RF_WriteReg(dev, 0x00, 0x01d7); mdelay(1); /* 6 */
- RF_WriteReg(dev, 0x03, 0x0e00); mdelay(1);
- RF_WriteReg(dev, 0x04, 0x0e50); mdelay(1);
-
- for (i = 0; i <= 36; i++) {
- RF_WriteReg(dev, 0x01, i); mdelay(1);
- RF_WriteReg(dev, 0x02, ZEBRA_RF_RX_GAIN_TABLE[i]); mdelay(1);
- }
-
- RF_WriteReg(dev, 0x05, 0x0203); mdelay(1); /* 203, 343 */
- RF_WriteReg(dev, 0x06, 0x0200); mdelay(1); /* 400 */
- /* switch to reg16-reg30, and HSSI disable 137 */
- RF_WriteReg(dev, 0x00, 0x0137); mdelay(1);
- mdelay(10); /* Deay 10 ms. */ /* 0xfd */
-
- /* Z4 synthesizer loop filter setting, 392 */
- RF_WriteReg(dev, 0x0d, 0x0008); mdelay(1);
- mdelay(10); /* Deay 10 ms. */ /* 0xfd */
-
- /* switch to reg0-reg15, and HSSI disable */
- RF_WriteReg(dev, 0x00, 0x0037); mdelay(1);
- mdelay(10); /* Deay 10 ms. */ /* 0xfd */
-
- /* CBC on, Tx Rx disable, High gain */
- RF_WriteReg(dev, 0x04, 0x0160); mdelay(1);
- mdelay(10); /* Deay 10 ms. */ /* 0xfd */
-
- /* Z4 setted channel 1 */
- RF_WriteReg(dev, 0x07, 0x0080); mdelay(1);
- mdelay(10); /* Deay 10 ms. */ /* 0xfd */
-
- RF_WriteReg(dev, 0x02, 0x088D); mdelay(1); /* LC calibration */
- mdelay(200); /* Deay 200 ms. */ /* 0xfd */
- mdelay(10); /* Deay 10 ms. */ /* 0xfd */
- mdelay(10); /* Deay 10 ms. */ /* 0xfd */
-
- /* switch to reg16-reg30 137, and HSSI disable 137 */
- RF_WriteReg(dev, 0x00, 0x0137); mdelay(1);
- mdelay(10); /* Deay 10 ms. */ /* 0xfd */
-
- RF_WriteReg(dev, 0x07, 0x0000); mdelay(1);
- RF_WriteReg(dev, 0x07, 0x0180); mdelay(1);
- RF_WriteReg(dev, 0x07, 0x0220); mdelay(1);
- RF_WriteReg(dev, 0x07, 0x03E0); mdelay(1);
-
- /* DAC calibration off 20070702 */
- RF_WriteReg(dev, 0x06, 0x00c1); mdelay(1);
- RF_WriteReg(dev, 0x0a, 0x0001); mdelay(1);
- /* For crystal calibration, added by Roger, 2007.12.11. */
- if (priv->bXtalCalibration) { /* reg 30. */
- /*
- * enable crystal calibration.
- * RF Reg[30], (1)Xin:[12:9], Xout:[8:5], addr[4:0].
- * (2)PA Pwr delay timer[15:14], default: 2.4us,
- * set BIT15=0
- * (3)RF signal on/off when calibration[13], default: on,
- * set BIT13=0.
- * So we should minus 4 BITs offset.
- */
- RF_WriteReg(dev, 0x0f, (priv->XtalCal_Xin<<5) |
- (priv->XtalCal_Xout<<1) | BIT11 | BIT9); mdelay(1);
- netdev_info(dev, "ZEBRA_Config_85BASIC_HardCode(): (%02x)\n",
- (priv->XtalCal_Xin<<5) | (priv->XtalCal_Xout<<1) |
- BIT11 | BIT9);
- } else {
- /* using default value. Xin=6, Xout=6. */
- RF_WriteReg(dev, 0x0f, 0x0acc); mdelay(1);
- }
- /* switch to reg0-reg15, and HSSI enable */
- RF_WriteReg(dev, 0x00, 0x00bf); mdelay(1);
- /* Rx BB start calibration, 00c//+edward */
- RF_WriteReg(dev, 0x0d, 0x08df); mdelay(1);
- /* temperature meter off */
- RF_WriteReg(dev, 0x02, 0x004d); mdelay(1);
- RF_WriteReg(dev, 0x04, 0x0975); mdelay(1); /* Rx mode */
- mdelay(10); /* Deay 10 ms.*/ /* 0xfe */
- mdelay(10); /* Deay 10 ms.*/ /* 0xfe */
- mdelay(10); /* Deay 10 ms.*/ /* 0xfe */
- /* Rx mode*/ /*+edward */
- RF_WriteReg(dev, 0x00, 0x0197); mdelay(1);
- /* Rx mode*/ /*+edward */
- RF_WriteReg(dev, 0x05, 0x05ab); mdelay(1);
- /* Rx mode*/ /*+edward */
- RF_WriteReg(dev, 0x00, 0x009f); mdelay(1);
- /* Rx mode*/ /*+edward */
- RF_WriteReg(dev, 0x01, 0x0000); mdelay(1);
- /* Rx mode*/ /*+edward */
- RF_WriteReg(dev, 0x02, 0x0000); mdelay(1);
- /* power save parameters. */
- u1b24E = read_nic_byte(dev, 0x24E);
- write_nic_byte(dev, 0x24E, (u1b24E & (~(BIT5|BIT6))));
-
- /*======================================================================
- *
- *======================================================================
- * CCKCONF.TXT
- *======================================================================
- *
- * [POWER SAVE] Power Saving Parameters by jong. 2007-11-27
- * CCK reg0x00[7]=1'b1 :power saving for TX (default)
- * CCK reg0x00[6]=1'b1: power saving for RX (default)
- * CCK reg0x06[4]=1'b1: turn off channel estimation related
- * circuits if not doing channel estimation.
- * CCK reg0x06[3]=1'b1: turn off unused circuits before cca = 1
- * CCK reg0x06[2]=1'b1: turn off cck's circuit if macrst =0
- */
-
- write_phy_cck(dev, 0x00, 0xc8);
- write_phy_cck(dev, 0x06, 0x1c);
- write_phy_cck(dev, 0x10, 0x78);
- write_phy_cck(dev, 0x2e, 0xd0);
- write_phy_cck(dev, 0x2f, 0x06);
- write_phy_cck(dev, 0x01, 0x46);
-
- /* power control */
- write_nic_byte(dev, CCK_TXAGC, 0x10);
- write_nic_byte(dev, OFDM_TXAGC, 0x1B);
- write_nic_byte(dev, ANTSEL, 0x03);
-
-
-
- /*
- *======================================================================
- * AGC.txt
- *======================================================================
- */
-
- write_phy_ofdm(dev, 0x00, 0x12);
-
- for (i = 0; i < 128; i++) {
-
- data = ZEBRA_AGC[i+1];
- data = data << 8;
- data = data | 0x0000008F;
-
- addr = i + 0x80; /* enable writing AGC table */
- addr = addr << 8;
- addr = addr | 0x0000008E;
-
- WriteBBPortUchar(dev, data);
- WriteBBPortUchar(dev, addr);
- WriteBBPortUchar(dev, 0x0000008E);
- }
-
- PlatformIOWrite4Byte(dev, PhyAddr, 0x00001080); /* Annie, 2006-05-05 */
-
- /*
- *======================================================================
- *
- *======================================================================
- * OFDMCONF.TXT
- *======================================================================
- */
-
- for (i = 0; i < 60; i++) {
- u4bRegOffset = i;
- u4bRegValue = OFDM_CONFIG[i];
-
- WriteBBPortUchar(dev,
- (0x00000080 |
- (u4bRegOffset & 0x7f) |
- ((u4bRegValue & 0xff) << 8)));
- }
-
- /*
- *======================================================================
- * by amy for antenna
- *======================================================================
- */
- /*
- * Config Sw/Hw Combinational Antenna Diversity. Added by Roger,
- * 2008.02.26.
- */
- SetAntennaConfig87SE(dev, priv->bDefaultAntenna1,
- priv->bSwAntennaDiverity);
-}
-
-
-void UpdateInitialGain(struct net_device *dev)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
- /* lzm add 080826 */
- if (priv->eRFPowerState != RF_ON) {
- /* Don't access BB/RF under disable PLL situation.
- * RT_TRACE(COMP_DIG, DBG_LOUD, ("UpdateInitialGain -
- * pHalData->eRFPowerState!=RF_ON\n"));
- * Back to the original state
- */
- priv->InitialGain = priv->InitialGainBackUp;
- return;
- }
-
- switch (priv->InitialGain) {
- case 1: /* m861dBm */
- write_phy_ofdm(dev, 0x17, 0x26); mdelay(1);
- write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
- write_phy_ofdm(dev, 0x05, 0xfa); mdelay(1);
- break;
-
- case 2: /* m862dBm */
- write_phy_ofdm(dev, 0x17, 0x36); mdelay(1);
- write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
- write_phy_ofdm(dev, 0x05, 0xfa); mdelay(1);
- break;
-
- case 3: /* m863dBm */
- write_phy_ofdm(dev, 0x17, 0x36); mdelay(1);
- write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
- write_phy_ofdm(dev, 0x05, 0xfb); mdelay(1);
- break;
-
- case 4: /* m864dBm */
- write_phy_ofdm(dev, 0x17, 0x46); mdelay(1);
- write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
- write_phy_ofdm(dev, 0x05, 0xfb); mdelay(1);
- break;
-
- case 5: /* m82dBm */
- write_phy_ofdm(dev, 0x17, 0x46); mdelay(1);
- write_phy_ofdm(dev, 0x24, 0x96); mdelay(1);
- write_phy_ofdm(dev, 0x05, 0xfb); mdelay(1);
- break;
-
- case 6: /* m78dBm */
- write_phy_ofdm(dev, 0x17, 0x56); mdelay(1);
- write_phy_ofdm(dev, 0x24, 0x96); mdelay(1);
- write_phy_ofdm(dev, 0x05, 0xfc); mdelay(1);
- break;
-
- case 7: /* m74dBm */
- write_phy_ofdm(dev, 0x17, 0x56); mdelay(1);
- write_phy_ofdm(dev, 0x24, 0xa6); mdelay(1);
- write_phy_ofdm(dev, 0x05, 0xfc); mdelay(1);
- break;
-
- case 8:
- write_phy_ofdm(dev, 0x17, 0x66); mdelay(1);
- write_phy_ofdm(dev, 0x24, 0xb6); mdelay(1);
- write_phy_ofdm(dev, 0x05, 0xfc); mdelay(1);
- break;
-
- default: /* MP */
- write_phy_ofdm(dev, 0x17, 0x26); mdelay(1);
- write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
- write_phy_ofdm(dev, 0x05, 0xfa); mdelay(1);
- break;
- }
-}
-/*
- * Description:
- * Tx Power tracking mechanism routine on 87SE.
- * Created by Roger, 2007.12.11.
- */
-static void InitTxPwrTracking87SE(struct net_device *dev)
-{
- u32 u4bRfReg;
-
- u4bRfReg = RF_ReadReg(dev, 0x02);
-
- /* Enable Thermal meter indication. */
- RF_WriteReg(dev, 0x02, u4bRfReg|PWR_METER_EN); mdelay(1);
-}
-
-static void PhyConfig8185(struct net_device *dev)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- write_nic_dword(dev, RCR, priv->ReceiveConfig);
- priv->RFProgType = read_nic_byte(dev, CONFIG4) & 0x03;
- /* RF config */
- ZEBRA_Config_85BASIC_HardCode(dev);
- /* Set default initial gain state to 4, approved by SD3 DZ, by Bruce,
- * 2007-06-06.
- */
- if (priv->bDigMechanism) {
- if (priv->InitialGain == 0)
- priv->InitialGain = 4;
- }
-
- /*
- * Enable thermal meter indication to implement TxPower tracking
- * on 87SE. We initialize thermal meter here to avoid unsuccessful
- * configuration. Added by Roger, 2007.12.11.
- */
- if (priv->bTxPowerTrack)
- InitTxPwrTracking87SE(dev);
-
- priv->InitialGainBackUp = priv->InitialGain;
- UpdateInitialGain(dev);
-
- return;
-}
-
-static void HwConfigureRTL8185(struct net_device *dev)
-{
- /*
- * RTL8185_TODO: Determine Retrylimit, TxAGC,
- * AutoRateFallback control.
- */
- u8 bUNIVERSAL_CONTROL_RL = 0;
- u8 bUNIVERSAL_CONTROL_AGC = 1;
- u8 bUNIVERSAL_CONTROL_ANT = 1;
- u8 bAUTO_RATE_FALLBACK_CTL = 1;
- u8 val8;
- write_nic_word(dev, BRSR, 0x0fff);
- /* Retry limit */
- val8 = read_nic_byte(dev, CW_CONF);
-
- if (bUNIVERSAL_CONTROL_RL)
- val8 = val8 & 0xfd;
- else
- val8 = val8 | 0x02;
-
- write_nic_byte(dev, CW_CONF, val8);
-
- /* Tx AGC */
- val8 = read_nic_byte(dev, TXAGC_CTL);
- if (bUNIVERSAL_CONTROL_AGC) {
- write_nic_byte(dev, CCK_TXAGC, 128);
- write_nic_byte(dev, OFDM_TXAGC, 128);
- val8 = val8 & 0xfe;
- } else {
- val8 = val8 | 0x01;
- }
-
-
- write_nic_byte(dev, TXAGC_CTL, val8);
-
- /* Tx Antenna including Feedback control */
- val8 = read_nic_byte(dev, TXAGC_CTL);
-
- if (bUNIVERSAL_CONTROL_ANT) {
- write_nic_byte(dev, ANTSEL, 0x00);
- val8 = val8 & 0xfd;
- } else {
- val8 = val8 & (val8|0x02); /* xiong-2006-11-15 */
- }
-
- write_nic_byte(dev, TXAGC_CTL, val8);
-
- /* Auto Rate fallback control */
- val8 = read_nic_byte(dev, RATE_FALLBACK);
- val8 &= 0x7c;
- if (bAUTO_RATE_FALLBACK_CTL) {
- val8 |= RATE_FALLBACK_CTL_ENABLE | RATE_FALLBACK_CTL_AUTO_STEP1;
-
- /* <RJ_TODO_8185B> We shall set up the ARFR according
- * to user's setting.
- */
- PlatformIOWrite2Byte(dev, ARFR, 0x0fff); /* set 1M ~ 54Mbps. */
- }
- write_nic_byte(dev, RATE_FALLBACK, val8);
-}
-
-static void MacConfig_85BASIC_HardCode(struct net_device *dev)
-{
- /*
- *======================================================================
- * MACREG.TXT
- *======================================================================
- */
- int nLinesRead = 0;
- u32 u4bRegOffset, u4bRegValue, u4bPageIndex = 0;
- int i;
-
- nLinesRead = sizeof(MAC_REG_TABLE)/2;
-
- for (i = 0; i < nLinesRead; i++) { /* nLinesRead=101 */
- u4bRegOffset = MAC_REG_TABLE[i][0];
- u4bRegValue = MAC_REG_TABLE[i][1];
-
- if (u4bRegOffset == 0x5e)
- u4bPageIndex = u4bRegValue;
- else
- u4bRegOffset |= (u4bPageIndex << 8);
-
- write_nic_byte(dev, u4bRegOffset, (u8)u4bRegValue);
- }
- /* ================================================================= */
-}
-
-static void MacConfig_85BASIC(struct net_device *dev)
-{
-
- u8 u1DA;
- MacConfig_85BASIC_HardCode(dev);
-
- /* ================================================================= */
-
- /* Follow TID_AC_MAP of WMac. */
- write_nic_word(dev, TID_AC_MAP, 0xfa50);
-
- /* Interrupt Migration, Jong suggested we use set 0x0000 first,
- * 2005.12.14, by rcnjko.
- */
- write_nic_word(dev, IntMig, 0x0000);
-
- /* Prevent TPC to cause CRC error. Added by Annie, 2006-06-10. */
- PlatformIOWrite4Byte(dev, 0x1F0, 0x00000000);
- PlatformIOWrite4Byte(dev, 0x1F4, 0x00000000);
- PlatformIOWrite1Byte(dev, 0x1F8, 0x00);
-
- /* Asked for by SD3 CM Lin, 2006.06.27, by rcnjko. */
-
- /*
- * power save parameter based on
- * "87SE power save parameters 20071127.doc", as follow.
- */
-
- /* Enable DA10 TX power saving */
- u1DA = read_nic_byte(dev, PHYPR);
- write_nic_byte(dev, PHYPR, (u1DA | BIT2));
-
- /* POWER: */
- write_nic_word(dev, 0x360, 0x1000);
- write_nic_word(dev, 0x362, 0x1000);
-
- /* AFE. */
- write_nic_word(dev, 0x370, 0x0560);
- write_nic_word(dev, 0x372, 0x0560);
- write_nic_word(dev, 0x374, 0x0DA4);
- write_nic_word(dev, 0x376, 0x0DA4);
- write_nic_word(dev, 0x378, 0x0560);
- write_nic_word(dev, 0x37A, 0x0560);
- write_nic_word(dev, 0x37C, 0x00EC);
- write_nic_word(dev, 0x37E, 0x00EC); /* +edward */
- write_nic_byte(dev, 0x24E, 0x01);
-}
-
-static u8 GetSupportedWirelessMode8185(struct net_device *dev)
-{
- return WIRELESS_MODE_B | WIRELESS_MODE_G;
-}
-
-static void
-ActUpdateChannelAccessSetting(struct net_device *dev,
- enum wireless_mode mode,
- struct chnl_access_setting *chnl_access_setting)
-{
- AC_CODING eACI;
-
- /*
- * <RJ_TODO_8185B>
- * TODO: We still don't know how to set up these registers,
- * just follow WMAC to verify 8185B FPAG.
- *
- * <RJ_TODO_8185B>
- * Jong said CWmin/CWmax register are not functional in 8185B,
- * so we shall fill channel access realted register into AC
- * parameter registers,
- * even in nQBss.
- */
-
- /* Suggested by Jong, 2005.12.08. */
- chnl_access_setting->sifs_timer = 0x22;
- chnl_access_setting->difs_timer = 0x1C; /* 2006.06.02, by rcnjko. */
- chnl_access_setting->slot_time_timer = 9; /* 2006.06.02, by rcnjko. */
- /*
- * Suggested by wcchu, it is the default value of EIFS register,
- * 2005.12.08.
- */
- chnl_access_setting->eifs_timer = 0x5B;
- chnl_access_setting->cwmin_index = 3; /* 2006.06.02, by rcnjko. */
- chnl_access_setting->cwmax_index = 7; /* 2006.06.02, by rcnjko. */
-
- write_nic_byte(dev, SIFS, chnl_access_setting->sifs_timer);
- /*
- * Rewrited from directly use PlatformEFIOWrite1Byte(),
- * by Annie, 2006-03-29.
- */
- write_nic_byte(dev, SLOT, chnl_access_setting->slot_time_timer);
-
- write_nic_byte(dev, EIFS, chnl_access_setting->eifs_timer);
-
- /*
- * <RJ_EXPR_QOS> Suggested by wcchu, it is the default value of EIFS
- * register, 2005.12.08.
- */
- write_nic_byte(dev, AckTimeOutReg, 0x5B);
-
- for (eACI = 0; eACI < AC_MAX; eACI++)
- write_nic_byte(dev, ACM_CONTROL, 0);
-}
-
-static void ActSetWirelessMode8185(struct net_device *dev, u8 btWirelessMode)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- struct ieee80211_device *ieee = priv->ieee80211;
- u8 btSupportedWirelessMode = GetSupportedWirelessMode8185(dev);
-
- if ((btWirelessMode & btSupportedWirelessMode) == 0) {
- /*
- * Don't switch to unsupported wireless mode, 2006.02.15,
- * by rcnjko.
- */
- DMESGW("ActSetWirelessMode8185(): WirelessMode(%d) is not supported (%d)!\n",
- btWirelessMode, btSupportedWirelessMode);
- return;
- }
-
- /* 1. Assign wireless mode to switch if necessary. */
- if (btWirelessMode == WIRELESS_MODE_AUTO) {
- if ((btSupportedWirelessMode & WIRELESS_MODE_A)) {
- btWirelessMode = WIRELESS_MODE_A;
- } else if (btSupportedWirelessMode & WIRELESS_MODE_G) {
- btWirelessMode = WIRELESS_MODE_G;
-
- } else if ((btSupportedWirelessMode & WIRELESS_MODE_B)) {
- btWirelessMode = WIRELESS_MODE_B;
- } else {
- DMESGW("ActSetWirelessMode8185(): No valid wireless mode supported, btSupportedWirelessMode(%x)!!!\n",
- btSupportedWirelessMode);
- btWirelessMode = WIRELESS_MODE_B;
- }
- }
-
- /*
- * 2. Swtich band: RF or BB specific actions,
- * for example, refresh tables in omc8255, or change initial gain if
- * necessary. Nothing to do for Zebra to switch band. Update current
- * wireless mode if we switch to specified band successfully.
- */
-
- ieee->mode = (enum wireless_mode)btWirelessMode;
-
- /* 3. Change related setting. */
- if (ieee->mode == WIRELESS_MODE_A)
- DMESG("WIRELESS_MODE_A\n");
- else if (ieee->mode == WIRELESS_MODE_B)
- DMESG("WIRELESS_MODE_B\n");
- else if (ieee->mode == WIRELESS_MODE_G)
- DMESG("WIRELESS_MODE_G\n");
-
- ActUpdateChannelAccessSetting(dev, ieee->mode,
- &priv->ChannelAccessSetting);
-}
-
-void rtl8185b_irq_enable(struct net_device *dev)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
- priv->irq_enabled = 1;
- write_nic_dword(dev, IMR, priv->IntrMask);
-}
-
-static void MgntDisconnectIBSS(struct net_device *dev)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- u8 i;
-
- for (i = 0; i < 6; i++)
- priv->ieee80211->current_network.bssid[i] = 0x55;
-
-
-
- priv->ieee80211->state = IEEE80211_NOLINK;
- /*
- * Stop Beacon.
- *
- * Vista add a Adhoc profile, HW radio off until
- * OID_DOT11_RESET_REQUEST Driver would set MSR=NO_LINK,
- * then HW Radio ON, MgntQueue Stuck. Because Bcn DMA isn't
- * complete, mgnt queue would stuck until Bcn packet send.
- *
- * Disable Beacon Queue Own bit, suggested by jong
- */
- ieee80211_stop_send_beacons(priv->ieee80211);
-
- priv->ieee80211->link_change(dev);
- notify_wx_assoc_event(priv->ieee80211);
-}
-
-static void MlmeDisassociateRequest(struct net_device *dev, u8 *asSta, u8 asRsn)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- u8 i;
-
- SendDisassociation(priv->ieee80211, asSta, asRsn);
-
- if (memcmp(priv->ieee80211->current_network.bssid, asSta, 6) == 0) {
- /* ShuChen TODO: change media status. */
-
- for (i = 0; i < 6; i++)
- priv->ieee80211->current_network.bssid[i] = 0x22;
-
- ieee80211_disassociate(priv->ieee80211);
- }
-}
-
-static void MgntDisconnectAP(struct net_device *dev, u8 asRsn)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
- /*
- * Commented out by rcnjko, 2005.01.27:
- * I move SecClearAllKeys() to MgntActSet_802_11_DISASSOCIATE().
- *
- * 2004/09/15, kcwu, the key should be cleared, or the new
- * handshaking will not success
- *
- * In WPA WPA2 need to Clear all key ... because new key will set
- * after new handshaking. 2004.10.11, by rcnjko.
- */
- MlmeDisassociateRequest(dev, priv->ieee80211->current_network.bssid,
- asRsn);
-
- priv->ieee80211->state = IEEE80211_NOLINK;
-}
-
-static bool MgntDisconnect(struct net_device *dev, u8 asRsn)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- /*
- * Schedule an workitem to wake up for ps mode, 070109, by rcnjko.
- */
-
- if (IS_DOT11D_ENABLE(priv->ieee80211))
- Dot11d_Reset(priv->ieee80211);
- /* In adhoc mode, update beacon frame. */
- if (priv->ieee80211->state == IEEE80211_LINKED) {
- if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
- MgntDisconnectIBSS(dev);
-
- if (priv->ieee80211->iw_mode == IW_MODE_INFRA) {
- /*
- * We clear key here instead of MgntDisconnectAP()
- * because that MgntActSet_802_11_DISASSOCIATE()
- * is an interface called by OS, e.g.
- * OID_802_11_DISASSOCIATE in Windows while as
- * MgntDisconnectAP() is used to handle
- * disassociation related things to AP, e.g. send
- * Disassoc frame to AP. 2005.01.27, by rcnjko.
- */
- MgntDisconnectAP(dev, asRsn);
- }
- /* Indicate Disconnect, 2005.02.23, by rcnjko. */
- }
- return true;
-}
-/*
- * Description:
- * Chang RF Power State.
- * Note that, only MgntActSet_RF_State() is allowed to set
- * HW_VAR_RF_STATE.
- *
- * Assumption:
- * PASSIVE LEVEL.
- */
-static bool SetRFPowerState(struct net_device *dev,
- enum rt_rf_power_state eRFPowerState)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- bool bResult = false;
-
- if (eRFPowerState == priv->eRFPowerState)
- return bResult;
-
- bResult = SetZebraRFPowerState8185(dev, eRFPowerState);
-
- return bResult;
-}
-
-bool MgntActSet_RF_State(struct net_device *dev, enum rt_rf_power_state StateToSet,
- u32 ChangeSource)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- bool bActionAllowed = false;
- bool bConnectBySSID = false;
- enum rt_rf_power_state rtState;
- u16 RFWaitCounter = 0;
- unsigned long flag;
- /*
- * Prevent the race condition of RF state change. By Bruce,
- * 2007-11-28. Only one thread can change the RF state at one time,
- * and others should wait to be executed.
- */
- while (true) {
- spin_lock_irqsave(&priv->rf_ps_lock, flag);
- if (priv->RFChangeInProgress) {
- spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
- /* Set RF after the previous action is done. */
- while (priv->RFChangeInProgress) {
- RFWaitCounter++;
- udelay(1000); /* 1 ms */
-
- /*
- * Wait too long, return FALSE to avoid
- * to be stuck here.
- */
- if (RFWaitCounter > 1000) { /* 1sec */
- netdev_info(dev, "MgntActSet_RF_State(): Wait too long to set RF\n");
- /* TODO: Reset RF state? */
- return false;
- }
- }
- } else {
- priv->RFChangeInProgress = true;
- spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
- break;
- }
- }
- rtState = priv->eRFPowerState;
-
- switch (StateToSet) {
- case RF_ON:
- /*
- * Turn On RF no matter the IPS setting because we need to
- * update the RF state to Ndis under Vista, or the Windows
- * does not allow the driver to perform site survey any
- * more. By Bruce, 2007-10-02.
- */
- priv->RfOffReason &= (~ChangeSource);
-
- if (!priv->RfOffReason) {
- priv->RfOffReason = 0;
- bActionAllowed = true;
-
- if (rtState == RF_OFF &&
- ChangeSource >= RF_CHANGE_BY_HW)
- bConnectBySSID = true;
- }
- break;
-
- case RF_OFF:
- /* 070125, rcnjko: we always keep connected in AP mode. */
-
- if (priv->RfOffReason > RF_CHANGE_BY_IPS) {
- /*
- * 060808, Annie:
- * Disconnect to current BSS when radio off.
- * Asked by QuanTa.
- *
- * Calling MgntDisconnect() instead of
- * MgntActSet_802_11_DISASSOCIATE(), because
- * we do NOT need to set ssid to dummy ones.
- */
- MgntDisconnect(dev, disas_lv_ss);
- /*
- * Clear content of bssDesc[] and bssDesc4Query[]
- * to avoid reporting old bss to UI.
- */
- }
-
- priv->RfOffReason |= ChangeSource;
- bActionAllowed = true;
- break;
- case RF_SLEEP:
- priv->RfOffReason |= ChangeSource;
- bActionAllowed = true;
- break;
- default:
- break;
- }
-
- if (bActionAllowed) {
- /* Config HW to the specified mode. */
- SetRFPowerState(dev, StateToSet);
- }
-
- /* Release RF spinlock */
- spin_lock_irqsave(&priv->rf_ps_lock, flag);
- priv->RFChangeInProgress = false;
- spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
- return bActionAllowed;
-}
-
-static void InactivePowerSave(struct net_device *dev)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- /*
- * This flag "bSwRfProcessing", indicates the status of IPS
- * procedure, should be set if the IPS workitem is really
- * scheduled. The old code, sets this flag before scheduling the
- * IPS workitem and however, at the same time the previous IPS
- * workitem did not end yet, fails to schedule the current
- * workitem. Thus, bSwRfProcessing blocks the IPS procedure of
- * switching RF.
- */
- priv->bSwRfProcessing = true;
-
- MgntActSet_RF_State(dev, priv->eInactivePowerState, RF_CHANGE_BY_IPS);
-
- /*
- * To solve CAM values miss in RF OFF, rewrite CAM values after
- * RF ON. By Bruce, 2007-09-20.
- */
-
- priv->bSwRfProcessing = false;
-}
-
-/*
- * Description:
- * Enter the inactive power save mode. RF will be off
- */
-void IPSEnter(struct net_device *dev)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- enum rt_rf_power_state rtState;
- if (priv->bInactivePs) {
- rtState = priv->eRFPowerState;
-
- /*
- * Do not enter IPS in the following conditions:
- * (1) RF is already OFF or
- * Sleep (2) bSwRfProcessing (indicates the IPS is still
- * under going) (3) Connected (only disconnected can
- * trigger IPS)(4) IBSS (send Beacon)
- * (5) AP mode (send Beacon)
- */
- if (rtState == RF_ON && !priv->bSwRfProcessing
- && (priv->ieee80211->state != IEEE80211_LINKED)) {
- priv->eInactivePowerState = RF_OFF;
- InactivePowerSave(dev);
- }
- }
-}
-void IPSLeave(struct net_device *dev)
-{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- enum rt_rf_power_state rtState;
- if (priv->bInactivePs) {
- rtState = priv->eRFPowerState;
- if ((rtState == RF_OFF || rtState == RF_SLEEP) &&
- !priv->bSwRfProcessing
- && priv->RfOffReason <= RF_CHANGE_BY_IPS) {
- priv->eInactivePowerState = RF_ON;
- InactivePowerSave(dev);
- }
- }
-}
-
-void rtl8185b_adapter_start(struct net_device *dev)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- struct ieee80211_device *ieee = priv->ieee80211;
-
- u8 SupportedWirelessMode;
- u8 InitWirelessMode;
- u8 bInvalidWirelessMode = 0;
- u8 tmpu8;
- u8 btCR9346;
- u8 TmpU1b;
- u8 btPSR;
-
- write_nic_byte(dev, 0x24e, (BIT5|BIT6|BIT0));
- rtl8180_reset(dev);
-
- priv->dma_poll_mask = 0;
- priv->dma_poll_stop_mask = 0;
-
- HwConfigureRTL8185(dev);
- write_nic_dword(dev, MAC0, ((u32 *)dev->dev_addr)[0]);
- write_nic_word(dev, MAC4, ((u32 *)dev->dev_addr)[1] & 0xffff);
- /* default network type to 'No Link' */
- write_nic_byte(dev, MSR, read_nic_byte(dev, MSR) & 0xf3);
- write_nic_word(dev, BcnItv, 100);
- write_nic_word(dev, AtimWnd, 2);
- PlatformIOWrite2Byte(dev, FEMR, 0xFFFF);
- write_nic_byte(dev, WPA_CONFIG, 0);
- MacConfig_85BASIC(dev);
- /* Override the RFSW_CTRL (MAC offset 0x272-0x273), 2006.06.07,
- * by rcnjko.
- */
- /* BT_DEMO_BOARD type */
- PlatformIOWrite2Byte(dev, RFSW_CTRL, 0x569a);
-
- /*
- *---------------------------------------------------------------------
- * Set up PHY related.
- *---------------------------------------------------------------------
- */
- /* Enable Config3.PARAM_En to revise AnaaParm. */
- write_nic_byte(dev, CR9346, 0xc0); /* enable config register write */
- tmpu8 = read_nic_byte(dev, CONFIG3);
- write_nic_byte(dev, CONFIG3, (tmpu8 | CONFIG3_PARM_En));
- /* Turn on Analog power. */
- /* Asked for by William, otherwise, MAC 3-wire can't work,
- * 2006.06.27, by rcnjko.
- */
- write_nic_dword(dev, ANAPARAM2, ANAPARM2_ASIC_ON);
- write_nic_dword(dev, ANAPARAM, ANAPARM_ASIC_ON);
- write_nic_word(dev, ANAPARAM3, 0x0010);
-
- write_nic_byte(dev, CONFIG3, tmpu8);
- write_nic_byte(dev, CR9346, 0x00);
- /* enable EEM0 and EEM1 in 9346CR */
- btCR9346 = read_nic_byte(dev, CR9346);
- write_nic_byte(dev, CR9346, (btCR9346 | 0xC0));
-
- /* B cut use LED1 to control HW RF on/off */
- TmpU1b = read_nic_byte(dev, CONFIG5);
- TmpU1b = TmpU1b & ~BIT3;
- write_nic_byte(dev, CONFIG5, TmpU1b);
-
- /* disable EEM0 and EEM1 in 9346CR */
- btCR9346 &= ~(0xC0);
- write_nic_byte(dev, CR9346, btCR9346);
-
- /* Enable Led (suggested by Jong) */
- /* B-cut RF Radio on/off 5e[3]=0 */
- btPSR = read_nic_byte(dev, PSR);
- write_nic_byte(dev, PSR, (btPSR | BIT3));
- /* setup initial timing for RFE. */
- write_nic_word(dev, RFPinsOutput, 0x0480);
- SetOutputEnableOfRfPins(dev);
- write_nic_word(dev, RFPinsSelect, 0x2488);
-
- /* PHY config. */
- PhyConfig8185(dev);
-
- /*
- * We assume RegWirelessMode has already been initialized before,
- * however, we has to validate the wireless mode here and provide a
- * reasonable initialized value if necessary. 2005.01.13,
- * by rcnjko.
- */
- SupportedWirelessMode = GetSupportedWirelessMode8185(dev);
- if ((ieee->mode != WIRELESS_MODE_B) &&
- (ieee->mode != WIRELESS_MODE_G) &&
- (ieee->mode != WIRELESS_MODE_A) &&
- (ieee->mode != WIRELESS_MODE_AUTO)) {
- /* It should be one of B, G, A, or AUTO. */
- bInvalidWirelessMode = 1;
- } else {
- /* One of B, G, A, or AUTO. */
- /* Check if the wireless mode is supported by RF. */
- if ((ieee->mode != WIRELESS_MODE_AUTO) &&
- (ieee->mode & SupportedWirelessMode) == 0) {
- bInvalidWirelessMode = 1;
- }
- }
-
- if (bInvalidWirelessMode || ieee->mode == WIRELESS_MODE_AUTO) {
- /* Auto or other invalid value. */
- /* Assigne a wireless mode to initialize. */
- if ((SupportedWirelessMode & WIRELESS_MODE_A)) {
- InitWirelessMode = WIRELESS_MODE_A;
- } else if ((SupportedWirelessMode & WIRELESS_MODE_G)) {
- InitWirelessMode = WIRELESS_MODE_G;
- } else if ((SupportedWirelessMode & WIRELESS_MODE_B)) {
- InitWirelessMode = WIRELESS_MODE_B;
- } else {
- DMESGW("InitializeAdapter8185(): No valid wireless mode supported, SupportedWirelessMode(%x)!!!\n",
- SupportedWirelessMode);
- InitWirelessMode = WIRELESS_MODE_B;
- }
-
- /* Initialize RegWirelessMode if it is not a valid one. */
- if (bInvalidWirelessMode)
- ieee->mode = (enum wireless_mode)InitWirelessMode;
-
- } else {
- /* One of B, G, A. */
- InitWirelessMode = ieee->mode;
- }
- priv->eRFPowerState = RF_OFF;
- priv->RfOffReason = 0;
- {
- MgntActSet_RF_State(dev, RF_ON, 0);
- }
- /*
- * If inactive power mode is enabled, disable rf while in
- * disconnected state.
- */
- if (priv->bInactivePs)
- MgntActSet_RF_State(dev , RF_OFF, RF_CHANGE_BY_IPS);
-
- ActSetWirelessMode8185(dev, (u8)(InitWirelessMode));
-
- /* ----------------------------------------------------------------- */
-
- rtl8185b_irq_enable(dev);
-
- netif_start_queue(dev);
-}
-
-void rtl8185b_rx_enable(struct net_device *dev)
-{
- u8 cmd;
- /* for now we accept data, management & ctl frame*/
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
-
- if (dev->flags & IFF_PROMISC)
- DMESG("NIC in promisc mode");
-
- if (priv->ieee80211->iw_mode == IW_MODE_MONITOR || dev->flags &
- IFF_PROMISC) {
- priv->ReceiveConfig = priv->ReceiveConfig & (~RCR_APM);
- priv->ReceiveConfig = priv->ReceiveConfig | RCR_AAP;
- }
-
- if (priv->ieee80211->iw_mode == IW_MODE_MONITOR)
- priv->ReceiveConfig = priv->ReceiveConfig | RCR_ACF |
- RCR_APWRMGT | RCR_AICV;
-
-
- if (priv->crcmon == 1 && priv->ieee80211->iw_mode == IW_MODE_MONITOR)
- priv->ReceiveConfig = priv->ReceiveConfig | RCR_ACRC32;
-
- write_nic_dword(dev, RCR, priv->ReceiveConfig);
-
- fix_rx_fifo(dev);
-
- cmd = read_nic_byte(dev, CMD);
- write_nic_byte(dev, CMD, cmd | (1<<CMD_RX_ENABLE_SHIFT));
-
-}
-
-void rtl8185b_tx_enable(struct net_device *dev)
-{
- u8 cmd;
- u8 byte;
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
- write_nic_dword(dev, TCR, priv->TransmitConfig);
- byte = read_nic_byte(dev, MSR);
- byte |= MSR_LINK_ENEDCA;
- write_nic_byte(dev, MSR, byte);
-
- fix_tx_fifo(dev);
-
- cmd = read_nic_byte(dev, CMD);
- write_nic_byte(dev, CMD, cmd | (1<<CMD_TX_ENABLE_SHIFT));
-}
-
diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c
index 636ec553ae83..e305d43ebd06 100644
--- a/drivers/staging/rtl8188eu/core/rtw_recv.c
+++ b/drivers/staging/rtl8188eu/core/rtw_recv.c
@@ -545,20 +545,18 @@ static struct recv_frame *decryptor(struct adapter *padapter,
static struct recv_frame *portctrl(struct adapter *adapter,
struct recv_frame *precv_frame)
{
- u8 *psta_addr = NULL, *ptr;
+ u8 *psta_addr, *ptr;
uint auth_alg;
struct recv_frame *pfhdr;
struct sta_info *psta;
struct sta_priv *pstapriv;
struct recv_frame *prtnframe;
- u16 ether_type = 0;
+ u16 ether_type;
u16 eapol_type = 0x888e;/* for Funia BD's WPA issue */
struct rx_pkt_attrib *pattrib;
- __be16 be_tmp;
pstapriv = &adapter->stapriv;
- psta = rtw_get_stainfo(pstapriv, psta_addr);
auth_alg = adapter->securitypriv.dot11AuthAlgrthm;
@@ -566,24 +564,23 @@ static struct recv_frame *portctrl(struct adapter *adapter,
pfhdr = precv_frame;
pattrib = &pfhdr->attrib;
psta_addr = pattrib->ta;
+ psta = rtw_get_stainfo(pstapriv, psta_addr);
prtnframe = NULL;
RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("########portctrl:adapter->securitypriv.dot11AuthAlgrthm=%d\n", adapter->securitypriv.dot11AuthAlgrthm));
if (auth_alg == 2) {
+ /* get ether_type */
+ ptr = ptr + pfhdr->attrib.hdrlen + LLC_HEADER_SIZE;
+ memcpy(&ether_type, ptr, 2);
+ ether_type = ntohs((unsigned short)ether_type);
+
if ((psta != NULL) && (psta->ieee8021x_blocked)) {
/* blocked */
/* only accept EAPOL frame */
RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("########portctrl:psta->ieee8021x_blocked==1\n"));
- prtnframe = precv_frame;
-
- /* get ether_type */
- ptr = ptr+pfhdr->attrib.hdrlen+pfhdr->attrib.iv_len+LLC_HEADER_SIZE;
- memcpy(&be_tmp, ptr, 2);
- ether_type = ntohs(be_tmp);
-
if (ether_type == eapol_type) {
prtnframe = precv_frame;
} else {
diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
index 2636e7f3dbb8..cf30a08912d1 100644
--- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
@@ -359,7 +359,7 @@ static char *translate_scan(struct adapter *padapter,
if (wpa_len > 0) {
p = buf;
_rtw_memset(buf, 0, MAX_WPA_IE_LEN);
- p += sprintf(p, "wpa_ie =");
+ p += sprintf(p, "wpa_ie=");
for (i = 0; i < wpa_len; i++)
p += sprintf(p, "%02x", wpa_ie[i]);
@@ -376,7 +376,7 @@ static char *translate_scan(struct adapter *padapter,
if (rsn_len > 0) {
p = buf;
_rtw_memset(buf, 0, MAX_WPA_IE_LEN);
- p += sprintf(p, "rsn_ie =");
+ p += sprintf(p, "rsn_ie=");
for (i = 0; i < rsn_len; i++)
p += sprintf(p, "%02x", rsn_ie[i]);
_rtw_memset(&iwe, 0, sizeof(iwe));
@@ -2899,7 +2899,7 @@ static int rtw_p2p_get_status(struct net_device *dev,
/* Commented by Albert 2010/10/12 */
/* Because of the output size limitation, I had removed the "Role" information. */
/* About the "Role" information, we will use the new private IOCTL to get the "Role" information. */
- sprintf(extra, "\n\nStatus =%.2d\n", rtw_p2p_state(pwdinfo));
+ sprintf(extra, "\n\nStatus=%.2d\n", rtw_p2p_state(pwdinfo));
wrqu->data.length = strlen(extra);
return ret;
@@ -2918,7 +2918,7 @@ static int rtw_p2p_get_req_cm(struct net_device *dev,
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
- sprintf(extra, "\n\nCM =%s\n", pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req);
+ sprintf(extra, "\n\nCM=%s\n", pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req);
wrqu->data.length = strlen(extra);
return ret;
}
@@ -2935,7 +2935,7 @@ static int rtw_p2p_get_role(struct net_device *dev,
pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1], pwdinfo->p2p_peer_interface_addr[2],
pwdinfo->p2p_peer_interface_addr[3], pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]);
- sprintf(extra, "\n\nRole =%.2d\n", rtw_p2p_role(pwdinfo));
+ sprintf(extra, "\n\nRole=%.2d\n", rtw_p2p_role(pwdinfo));
wrqu->data.length = strlen(extra);
return ret;
}
@@ -3022,7 +3022,7 @@ static int rtw_p2p_get_op_ch(struct net_device *dev,
DBG_88E("[%s] Op_ch = %02x\n", __func__, pwdinfo->operating_channel);
- sprintf(extra, "\n\nOp_ch =%.2d\n", pwdinfo->operating_channel);
+ sprintf(extra, "\n\nOp_ch=%.2d\n", pwdinfo->operating_channel);
wrqu->data.length = strlen(extra);
return ret;
}
@@ -3043,7 +3043,7 @@ static int rtw_p2p_get_wps_configmethod(struct net_device *dev,
u8 blnMatch = 0;
u16 attr_content = 0;
uint attr_contentlen = 0;
- /* 6 is the string "wpsCM =", 17 is the MAC addr, we have to clear it at wrqu->data.pointer */
+ /* 6 is the string "wpsCM=", 17 is the MAC addr, we have to clear it at wrqu->data.pointer */
u8 attr_content_str[6 + 17] = {0x00};
/* Commented by Albert 20110727 */
@@ -3079,7 +3079,7 @@ static int rtw_p2p_get_wps_configmethod(struct net_device *dev,
rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_CONF_METHOD, (u8 *) &be_tmp, &attr_contentlen);
if (attr_contentlen) {
attr_content = be16_to_cpu(be_tmp);
- sprintf(attr_content_str, "\n\nM =%.4d", attr_content);
+ sprintf(attr_content_str, "\n\nM=%.4d", attr_content);
blnMatch = 1;
}
}
@@ -3091,7 +3091,7 @@ static int rtw_p2p_get_wps_configmethod(struct net_device *dev,
spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
if (!blnMatch)
- sprintf(attr_content_str, "\n\nM = 0000");
+ sprintf(attr_content_str, "\n\nM=0000");
if (copy_to_user(wrqu->data.pointer, attr_content_str, 6 + 17))
return -EFAULT;
@@ -3172,9 +3172,9 @@ static int rtw_p2p_get_go_device_address(struct net_device *dev,
spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
if (!blnMatch)
- snprintf(go_devadd_str, sizeof(go_devadd_str), "\n\ndev_add = NULL");
+ snprintf(go_devadd_str, sizeof(go_devadd_str), "\n\ndev_add=NULL");
else
- snprintf(go_devadd_str, sizeof(go_devadd_str), "\n\ndev_add =%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
+ snprintf(go_devadd_str, sizeof(go_devadd_str), "\n\ndev_add=%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
attr_content[0], attr_content[1], attr_content[2], attr_content[3], attr_content[4], attr_content[5]);
if (copy_to_user(wrqu->data.pointer, go_devadd_str, sizeof(go_devadd_str)))
@@ -3198,7 +3198,7 @@ static int rtw_p2p_get_device_type(struct net_device *dev,
u8 blnMatch = 0;
u8 dev_type[8] = {0x00};
uint dev_type_len = 0;
- u8 dev_type_str[17 + 9] = {0x00}; /* +9 is for the str "dev_type =", we have to clear it at wrqu->data.pointer */
+ u8 dev_type_str[17 + 9] = {0x00}; /* +9 is for the str "dev_type=", we have to clear it at wrqu->data.pointer */
/* Commented by Albert 20121209 */
/* The input data is the MAC address which the application wants to know its device type. */
@@ -3239,7 +3239,7 @@ static int rtw_p2p_get_device_type(struct net_device *dev,
memcpy(&be_tmp, dev_type, 2);
type = be16_to_cpu(be_tmp);
- sprintf(dev_type_str, "\n\nN =%.2d", type);
+ sprintf(dev_type_str, "\n\nN=%.2d", type);
blnMatch = 1;
}
}
@@ -3252,7 +3252,7 @@ static int rtw_p2p_get_device_type(struct net_device *dev,
spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
if (!blnMatch)
- sprintf(dev_type_str, "\n\nN = 00");
+ sprintf(dev_type_str, "\n\nN=00");
if (copy_to_user(wrqu->data.pointer, dev_type_str, 9 + 17)) {
return -EFAULT;
@@ -3277,7 +3277,7 @@ static int rtw_p2p_get_device_name(struct net_device *dev,
u8 blnMatch = 0;
u8 dev_name[WPS_MAX_DEVICE_NAME_LEN] = {0x00};
uint dev_len = 0;
- u8 dev_name_str[WPS_MAX_DEVICE_NAME_LEN + 5] = {0x00}; /* +5 is for the str "devN =", we have to clear it at wrqu->data.pointer */
+ u8 dev_name_str[WPS_MAX_DEVICE_NAME_LEN + 5] = {0x00}; /* +5 is for the str "devN=", we have to clear it at wrqu->data.pointer */
/* Commented by Albert 20121225 */
/* The input data is the MAC address which the application wants to know its device name. */
@@ -3310,7 +3310,7 @@ static int rtw_p2p_get_device_name(struct net_device *dev,
if (wpsie) {
rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_DEVICE_NAME, dev_name, &dev_len);
if (dev_len) {
- sprintf(dev_name_str, "\n\nN =%s", dev_name);
+ sprintf(dev_name_str, "\n\nN=%s", dev_name);
blnMatch = 1;
}
}
@@ -3323,7 +3323,7 @@ static int rtw_p2p_get_device_name(struct net_device *dev,
spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
if (!blnMatch)
- sprintf(dev_name_str, "\n\nN = 0000");
+ sprintf(dev_name_str, "\n\nN=0000");
if (copy_to_user(wrqu->data.pointer, dev_name_str, 5 + ((dev_len > 17) ? dev_len : 17)))
return -EFAULT;
@@ -3349,7 +3349,7 @@ static int rtw_p2p_get_invitation_procedure(struct net_device *dev,
u8 attr_content[2] = {0x00};
u8 inv_proc_str[17 + 8] = {0x00};
- /* +8 is for the str "InvProc =", we have to clear it at wrqu->data.pointer */
+ /* +8 is for the str "InvProc=", we have to clear it at wrqu->data.pointer */
/* Commented by Ouden 20121226 */
/* The application wants to know P2P initiation procedure is supported or not. */
@@ -3397,12 +3397,12 @@ static int rtw_p2p_get_invitation_procedure(struct net_device *dev,
spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
if (!blnMatch) {
- sprintf(inv_proc_str, "\nIP =-1");
+ sprintf(inv_proc_str, "\nIP=-1");
} else {
if (attr_content[0] & 0x20)
- sprintf(inv_proc_str, "\nIP = 1");
+ sprintf(inv_proc_str, "\nIP=1");
else
- sprintf(inv_proc_str, "\nIP = 0");
+ sprintf(inv_proc_str, "\nIP=0");
}
if (copy_to_user(wrqu->data.pointer, inv_proc_str, 8 + 17))
return -EFAULT;
@@ -3512,7 +3512,7 @@ static int rtw_p2p_invite_req(struct net_device *dev,
/* The input data contains two informations. */
/* 1. First information is the P2P device address which you want to send to. */
/* 2. Second information is the group id which combines with GO's mac address, space and GO's ssid. */
- /* Command line sample: iwpriv wlan0 p2p_set invite ="00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy" */
+ /* Command line sample: iwpriv wlan0 p2p_set invite="00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy" */
/* Format: 00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy */
DBG_88E("[%s] data = %s\n", __func__, extra);
@@ -3805,48 +3805,48 @@ static int rtw_p2p_set(struct net_device *dev,
#ifdef CONFIG_88EU_P2P
DBG_88E("[%s] extra = %s\n", __func__, extra);
- if (!memcmp(extra, "enable =", 7)) {
+ if (!memcmp(extra, "enable=", 7)) {
rtw_wext_p2p_enable(dev, info, wrqu, &extra[7]);
- } else if (!memcmp(extra, "setDN =", 6)) {
+ } else if (!memcmp(extra, "setDN=", 6)) {
wrqu->data.length -= 6;
rtw_p2p_setDN(dev, info, wrqu, &extra[6]);
- } else if (!memcmp(extra, "profilefound =", 13)) {
+ } else if (!memcmp(extra, "profilefound=", 13)) {
wrqu->data.length -= 13;
rtw_p2p_profilefound(dev, info, wrqu, &extra[13]);
- } else if (!memcmp(extra, "prov_disc =", 10)) {
+ } else if (!memcmp(extra, "prov_disc=", 10)) {
wrqu->data.length -= 10;
rtw_p2p_prov_disc(dev, info, wrqu, &extra[10]);
- } else if (!memcmp(extra, "nego =", 5)) {
+ } else if (!memcmp(extra, "nego=", 5)) {
wrqu->data.length -= 5;
rtw_p2p_connect(dev, info, wrqu, &extra[5]);
- } else if (!memcmp(extra, "intent =", 7)) {
+ } else if (!memcmp(extra, "intent=", 7)) {
/* Commented by Albert 2011/03/23 */
/* The wrqu->data.length will include the null character */
/* So, we will decrease 7 + 1 */
wrqu->data.length -= 8;
rtw_p2p_set_intent(dev, info, wrqu, &extra[7]);
- } else if (!memcmp(extra, "ssid =", 5)) {
+ } else if (!memcmp(extra, "ssid=", 5)) {
wrqu->data.length -= 5;
rtw_p2p_set_go_nego_ssid(dev, info, wrqu, &extra[5]);
- } else if (!memcmp(extra, "got_wpsinfo =", 12)) {
+ } else if (!memcmp(extra, "got_wpsinfo=", 12)) {
wrqu->data.length -= 12;
rtw_p2p_got_wpsinfo(dev, info, wrqu, &extra[12]);
- } else if (!memcmp(extra, "listen_ch =", 10)) {
+ } else if (!memcmp(extra, "listen_ch=", 10)) {
/* Commented by Albert 2011/05/24 */
/* The wrqu->data.length will include the null character */
/* So, we will decrease (10 + 1) */
wrqu->data.length -= 11;
rtw_p2p_set_listen_ch(dev, info, wrqu, &extra[10]);
- } else if (!memcmp(extra, "op_ch =", 6)) {
+ } else if (!memcmp(extra, "op_ch=", 6)) {
/* Commented by Albert 2011/05/24 */
/* The wrqu->data.length will include the null character */
/* So, we will decrease (6 + 1) */
wrqu->data.length -= 7;
rtw_p2p_set_op_ch(dev, info, wrqu, &extra[6]);
- } else if (!memcmp(extra, "invite =", 7)) {
+ } else if (!memcmp(extra, "invite=", 7)) {
wrqu->data.length -= 8;
rtw_p2p_invite_req(dev, info, wrqu, &extra[7]);
- } else if (!memcmp(extra, "persistent =", 11)) {
+ } else if (!memcmp(extra, "persistent=", 11)) {
wrqu->data.length -= 11;
rtw_p2p_set_persistent(dev, info, wrqu, &extra[11]);
}
@@ -3887,7 +3887,7 @@ static int rtw_p2p_get(struct net_device *dev,
"group_id", 8)) {
rtw_p2p_get_groupid(dev, info, wrqu, extra);
} else if (!memcmp((__force const char *)wrqu->data.pointer,
- "peer_deva_inv", 9)) {
+ "peer_deva_inv", 13)) {
/* Get the P2P device address when receiving the P2P Invitation request frame. */
rtw_p2p_get_peer_devaddr_by_invitation(dev, info, wrqu, extra);
} else if (!memcmp((__force const char *)wrqu->data.pointer,
@@ -6920,7 +6920,7 @@ static int rtw_mp_ctx(struct net_device *dev,
DBG_88E("%s: in =%s\n", __func__, extra);
- countPkTx = strncmp(extra, "count =", 5); /* strncmp true is 0 */
+ countPkTx = strncmp(extra, "count=", 6); /* strncmp true is 0 */
cotuTx = strncmp(extra, "background", 20);
CarrSprTx = strncmp(extra, "background, cs", 20);
scTx = strncmp(extra, "background, sc", 20);
@@ -7044,7 +7044,7 @@ static int rtw_mp_arx(struct net_device *dev,
DBG_88E("%s: %s\n", __func__, input);
bStartRx = (strncmp(input, "start", 5) == 0) ? 1 : 0; /* strncmp true is 0 */
- bStopRx = (strncmp(input, "stop", 5) == 0) ? 1 : 0; /* strncmp true is 0 */
+ bStopRx = (strncmp(input, "stop", 4) == 0) ? 1 : 0; /* strncmp true is 0 */
bQueryPhy = (strncmp(input, "phy", 3) == 0) ? 1 : 0; /* strncmp true is 0 */
if (bStartRx) {
diff --git a/drivers/staging/rtl8712/rtl871x_recv.c b/drivers/staging/rtl8712/rtl871x_recv.c
index 23ec684b60e1..274c359279ef 100644
--- a/drivers/staging/rtl8712/rtl871x_recv.c
+++ b/drivers/staging/rtl8712/rtl871x_recv.c
@@ -254,7 +254,7 @@ union recv_frame *r8712_portctrl(struct _adapter *adapter,
struct sta_info *psta;
struct sta_priv *pstapriv;
union recv_frame *prtnframe;
- u16 ether_type = 0;
+ u16 ether_type;
pstapriv = &adapter->stapriv;
ptr = get_recvframe_data(precv_frame);
@@ -263,15 +263,14 @@ union recv_frame *r8712_portctrl(struct _adapter *adapter,
psta = r8712_get_stainfo(pstapriv, psta_addr);
auth_alg = adapter->securitypriv.AuthAlgrthm;
if (auth_alg == 2) {
+ /* get ether_type */
+ ptr = ptr + pfhdr->attrib.hdrlen + LLC_HEADER_SIZE;
+ memcpy(&ether_type, ptr, 2);
+ ether_type = ntohs((unsigned short)ether_type);
+
if ((psta != NULL) && (psta->ieee8021x_blocked)) {
/* blocked
* only accept EAPOL frame */
- prtnframe = precv_frame;
- /*get ether_type */
- ptr = ptr + pfhdr->attrib.hdrlen +
- pfhdr->attrib.iv_len + LLC_HEADER_SIZE;
- memcpy(&ether_type, ptr, 2);
- ether_type = ntohs((unsigned short)ether_type);
if (ether_type == 0x888e)
prtnframe = precv_frame;
else {
diff --git a/drivers/staging/rtl8723au/core/rtw_ieee80211.c b/drivers/staging/rtl8723au/core/rtw_ieee80211.c
index 780631fd3b6d..a48ab25a7d8a 100644
--- a/drivers/staging/rtl8723au/core/rtw_ieee80211.c
+++ b/drivers/staging/rtl8723au/core/rtw_ieee80211.c
@@ -1496,45 +1496,23 @@ void rtw_wlan_bssid_ex_remove_p2p_attr23a(struct wlan_bssid_ex *bss_ex, u8 attr_
int rtw_get_wfd_ie(u8 *in_ie, int in_len, u8 *wfd_ie, uint *wfd_ielen)
{
int match;
- uint cnt = 0;
- u8 eid, wfd_oui[4] = {0x50, 0x6F, 0x9A, 0x0A};
+ const u8 *ie;
- match = false;
+ match = 0;
- if (in_len < 0) {
+ if (in_len < 0)
return match;
- }
-
- while (cnt < in_len)
- {
- eid = in_ie[cnt];
- if ((eid == _VENDOR_SPECIFIC_IE_) &&
- !memcmp(&in_ie[cnt+2], wfd_oui, 4)) {
- if (wfd_ie != NULL) {
- memcpy(wfd_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
-
- } else {
- if (wfd_ielen != NULL) {
- *wfd_ielen = 0;
- }
- }
-
- if (wfd_ielen != NULL) {
- *wfd_ielen = in_ie[cnt + 1] + 2;
- }
-
- cnt += in_ie[cnt + 1] + 2;
-
- match = true;
- break;
- } else {
- cnt += in_ie[cnt + 1] +2; /* goto next */
- }
- }
+ ie = cfg80211_find_vendor_ie(0x506F9A, 0x0A, in_ie, in_len);
+ if (ie && (ie[1] <= (MAX_WFD_IE_LEN - 2))) {
+ if (wfd_ie) {
+ *wfd_ielen = ie[1] + 2;
+ memcpy(wfd_ie, ie, ie[1] + 2);
+ } else
+ if (wfd_ielen)
+ *wfd_ielen = 0;
- if (match == true) {
- match = cnt;
+ match = 1;
}
return match;
diff --git a/drivers/staging/rtl8723au/core/rtw_mlme_ext.c b/drivers/staging/rtl8723au/core/rtw_mlme_ext.c
index 4c753639ea5a..1f3e8a0aece4 100644
--- a/drivers/staging/rtl8723au/core/rtw_mlme_ext.c
+++ b/drivers/staging/rtl8723au/core/rtw_mlme_ext.c
@@ -1281,7 +1281,7 @@ unsigned int OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *prec
u8 p2p_status_code = P2P_STATUS_SUCCESS;
u8 *p2pie;
u32 p2pielen = 0;
- u8 wfd_ie[ 128 ] = { 0x00 };
+ u8 wfd_ie[MAX_WFD_IE_LEN] = { 0x00 };
u32 wfd_ielen = 0;
#endif /* CONFIG_8723AU_P2P */
diff --git a/drivers/staging/rtl8723au/core/rtw_p2p.c b/drivers/staging/rtl8723au/core/rtw_p2p.c
index 27a6cc76973d..1a961e3f3a55 100644
--- a/drivers/staging/rtl8723au/core/rtw_p2p.c
+++ b/drivers/staging/rtl8723au/core/rtw_p2p.c
@@ -2535,7 +2535,7 @@ u8 process_p2p_group_negotation_req23a(struct wifidirect_info *pwdinfo, u8 *pfra
u16 wps_devicepassword_id = 0x0000;
uint wps_devicepassword_id_len = 0;
#ifdef CONFIG_8723AU_P2P
- u8 wfd_ie[ 128 ] = { 0x00 };
+ u8 wfd_ie[MAX_WFD_IE_LEN] = { 0x00 };
u32 wfd_ielen = 0;
#endif /* CONFIG_8723AU_P2P */
@@ -2741,7 +2741,7 @@ u8 process_p2p_group_negotation_resp23a(struct wifidirect_info *pwdinfo, u8 *pfr
u32 ies_len;
u8 * p2p_ie;
#ifdef CONFIG_8723AU_P2P
- u8 wfd_ie[ 128 ] = { 0x00 };
+ u8 wfd_ie[MAX_WFD_IE_LEN] = { 0x00 };
u32 wfd_ielen = 0;
#endif /* CONFIG_8723AU_P2P */
diff --git a/drivers/staging/rtl8723au/core/rtw_wlan_util.c b/drivers/staging/rtl8723au/core/rtw_wlan_util.c
index 0dfcfbce3b52..99d81e612e7b 100644
--- a/drivers/staging/rtl8723au/core/rtw_wlan_util.c
+++ b/drivers/staging/rtl8723au/core/rtw_wlan_util.c
@@ -570,7 +570,7 @@ void flush_all_cam_entry23a(struct rtw_adapter *padapter)
int WFD_info_handler(struct rtw_adapter *padapter, struct ndis_802_11_var_ies * pIE)
{
struct wifidirect_info *pwdinfo;
- u8 wfd_ie[128] = {0x00};
+ u8 wfd_ie[MAX_WFD_IE_LEN] = {0x00};
u32 wfd_ielen = 0;
pwdinfo = &padapter->wdinfo;
@@ -681,7 +681,7 @@ void WMMOnAssocRsp23a(struct rtw_adapter *padapter)
inx[0] = 0; inx[1] = 1; inx[2] = 2; inx[3] = 3;
if (pregpriv->wifi_spec == 1) {
- u32 j, tmp, change_inx;
+ u32 j, tmp, change_inx = false;
/* entry indx: 0->vo, 1->vi, 2->be, 3->bk. */
for (i = 0; i < 4; i++) {
diff --git a/drivers/staging/rtl8723au/os_dep/os_intfs.c b/drivers/staging/rtl8723au/os_dep/os_intfs.c
index 57eca7a45672..4fe751f7c2bf 100644
--- a/drivers/staging/rtl8723au/os_dep/os_intfs.c
+++ b/drivers/staging/rtl8723au/os_dep/os_intfs.c
@@ -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);
diff --git a/drivers/staging/rtl8723au/os_dep/usb_ops_linux.c b/drivers/staging/rtl8723au/os_dep/usb_ops_linux.c
index c49160e477d8..07e542e5d156 100644
--- a/drivers/staging/rtl8723au/os_dep/usb_ops_linux.c
+++ b/drivers/staging/rtl8723au/os_dep/usb_ops_linux.c
@@ -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);
diff --git a/drivers/staging/rtl8821ae/base.c b/drivers/staging/rtl8821ae/base.c
index e5073fe24770..a4c9cc437bc6 100644
--- a/drivers/staging/rtl8821ae/base.c
+++ b/drivers/staging/rtl8821ae/base.c
@@ -388,7 +388,7 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw)
}
-static void _rtl_init_deferred_work(struct ieee80211_hw *hw)
+static int _rtl_init_deferred_work(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -410,6 +410,9 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw)
rtlpriv->works.rtl_wq = create_workqueue(rtlpriv->cfg->name);
#endif
/*<delete in kernel end>*/
+ if (!rtlpriv->works.rtl_wq)
+ return -ENOMEM;
+
INIT_DELAYED_WORK(&rtlpriv->works.watchdog_wq,
(void *)rtl_watchdog_wq_callback);
INIT_DELAYED_WORK(&rtlpriv->works.ips_nic_off_wq,
@@ -421,6 +424,8 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw)
INIT_DELAYED_WORK(&rtlpriv->works.fwevt_wq,
(void *)rtl_fwevt_wq_callback);
+ return 0;
+
}
void rtl_deinit_deferred_work(struct ieee80211_hw *hw)
@@ -519,7 +524,8 @@ int rtl_init_core(struct ieee80211_hw *hw)
INIT_LIST_HEAD(&rtlpriv->entry_list);
/* <6> init deferred work */
- _rtl_init_deferred_work(hw);
+ if (_rtl_init_deferred_work(hw))
+ return 1;
/* <7> */
#ifdef VIF_TODO
diff --git a/drivers/staging/speakup/main.c b/drivers/staging/speakup/main.c
index ef5933b93590..3b6e5358c723 100644
--- a/drivers/staging/speakup/main.c
+++ b/drivers/staging/speakup/main.c
@@ -1855,8 +1855,9 @@ static int handle_goto(struct vc_data *vc, u_char type, u_char ch, u_short key)
{
static u_char goto_buf[8];
static int num;
- int maxlen, go_pos;
+ int maxlen;
char *cp;
+
if (type == KT_SPKUP && ch == SPEAKUP_GOTO)
goto do_goto;
if (type == KT_LATIN && ch == '\n')
@@ -1891,25 +1892,24 @@ oops:
spk_special_handler = NULL;
return 1;
}
- go_pos = kstrtol(goto_buf, 10, (long *)&cp);
- goto_pos = (u_long) go_pos;
+
+ goto_pos = simple_strtoul(goto_buf, &cp, 10);
+
if (*cp == 'x') {
if (*goto_buf < '0')
goto_pos += spk_x;
- else
+ else if (goto_pos > 0)
goto_pos--;
- if (goto_pos < 0)
- goto_pos = 0;
+
if (goto_pos >= vc->vc_cols)
goto_pos = vc->vc_cols - 1;
goto_x = 1;
} else {
if (*goto_buf < '0')
goto_pos += spk_y;
- else
+ else if (goto_pos > 0)
goto_pos--;
- if (goto_pos < 0)
- goto_pos = 0;
+
if (goto_pos >= vc->vc_rows)
goto_pos = vc->vc_rows - 1;
goto_x = 0;
diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c
index 8ea9c46e56ae..3152a2180c45 100644
--- a/drivers/staging/unisys/uislib/uislib.c
+++ b/drivers/staging/unisys/uislib/uislib.c
@@ -381,17 +381,17 @@ create_bus(CONTROLVM_MESSAGE *msg, char *buf)
cmd.add_vbus.busTypeGuid = msg->cmd.createBus.busDataTypeGuid;
cmd.add_vbus.busInstGuid = msg->cmd.createBus.busInstGuid;
if (!VirtControlChanFunc) {
- kfree(bus);
LOGERR("CONTROLVM_BUS_CREATE Failed: virtpci callback not registered.");
POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus->busNo,
POSTCODE_SEVERITY_ERR);
+ kfree(bus);
return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
}
if (!VirtControlChanFunc(&cmd)) {
- kfree(bus);
LOGERR("CONTROLVM_BUS_CREATE Failed: virtpci GUEST_ADD_VBUS returned error.");
POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus->busNo,
POSTCODE_SEVERITY_ERR);
+ kfree(bus);
return
CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
}
diff --git a/drivers/staging/unisys/visorchipset/visorchipset.h b/drivers/staging/unisys/visorchipset/visorchipset.h
index d4bf203cdfdf..d95825dc5414 100644
--- a/drivers/staging/unisys/visorchipset/visorchipset.h
+++ b/drivers/staging/unisys/visorchipset/visorchipset.h
@@ -104,9 +104,9 @@ finddevice(struct list_head *list, U32 busNo, U32 devNo)
static inline void delbusdevices(struct list_head *list, U32 busNo)
{
- VISORCHIPSET_DEVICE_INFO *p;
+ VISORCHIPSET_DEVICE_INFO *p, *tmp;
- list_for_each_entry(p, list, entry) {
+ list_for_each_entry_safe(p, tmp, list, entry) {
if (p->busNo == busNo) {
list_del(&p->entry);
kfree(p);
diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c
index 257c6e59b460..c475e256e34b 100644
--- a/drivers/staging/unisys/visorchipset/visorchipset_main.c
+++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c
@@ -605,16 +605,16 @@ EXPORT_SYMBOL_GPL(visorchipset_register_busdev_client);
static void
cleanup_controlvm_structures(void)
{
- VISORCHIPSET_BUS_INFO *bi;
- VISORCHIPSET_DEVICE_INFO *di;
+ VISORCHIPSET_BUS_INFO *bi, *tmp_bi;
+ VISORCHIPSET_DEVICE_INFO *di, *tmp_di;
- list_for_each_entry(bi, &BusInfoList, entry) {
+ list_for_each_entry_safe(bi, tmp_bi, &BusInfoList, entry) {
busInfo_clear(bi);
list_del(&bi->entry);
kfree(bi);
}
- list_for_each_entry(di, &DevInfoList, entry) {
+ list_for_each_entry_safe(di, tmp_di, &DevInfoList, entry) {
devInfo_clear(di);
list_del(&di->entry);
kfree(di);
diff --git a/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c b/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c
index c5bf60b135b9..92caef7474c7 100644
--- a/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c
+++ b/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c
@@ -118,6 +118,7 @@ static int refresh_exported_devices(void)
struct udev_list_entry *devices, *dev_list_entry;
struct udev_device *dev;
const char *path;
+ const char *driver;
enumerate = udev_enumerate_new(udev_context);
udev_enumerate_add_match_subsystem(enumerate, "usb");
@@ -128,10 +129,12 @@ static int refresh_exported_devices(void)
udev_list_entry_foreach(dev_list_entry, devices) {
path = udev_list_entry_get_name(dev_list_entry);
dev = udev_device_new_from_syspath(udev_context, path);
+ if (dev == NULL)
+ continue;
/* Check whether device uses usbip-host driver. */
- if (!strcmp(udev_device_get_driver(dev),
- USBIP_HOST_DRV_NAME)) {
+ driver = udev_device_get_driver(dev);
+ if (driver != NULL && !strcmp(driver, USBIP_HOST_DRV_NAME)) {
edev = usbip_exported_device_new(path);
if (!edev) {
dbg("usbip_exported_device_new failed");
diff --git a/drivers/staging/usbip/vhci_sysfs.c b/drivers/staging/usbip/vhci_sysfs.c
index 47bddcdde0a6..211f43f67ea2 100644
--- a/drivers/staging/usbip/vhci_sysfs.c
+++ b/drivers/staging/usbip/vhci_sysfs.c
@@ -184,7 +184,7 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
* @devid: unique device identifier in a remote host
* @speed: usb device speed in a remote host
*/
- if (sscanf(buf, "%u %u %u %u", &rhport, &sockfd, &devid, &speed) != 1)
+ if (sscanf(buf, "%u %u %u %u", &rhport, &sockfd, &devid, &speed) != 4)
return -EINVAL;
usbip_dbg_vhci_sysfs("rhport(%u) sockfd(%u) devid(%u) speed(%u)\n",
diff --git a/drivers/staging/vme/devices/vme_user.c b/drivers/staging/vme/devices/vme_user.c
index 792792715673..ffb4eeefdddb 100644
--- a/drivers/staging/vme/devices/vme_user.c
+++ b/drivers/staging/vme/devices/vme_user.c
@@ -776,7 +776,8 @@ static int vme_user_probe(struct vme_dev *vdev)
image[i].kern_buf = kmalloc(image[i].size_buf, GFP_KERNEL);
if (image[i].kern_buf == NULL) {
err = -ENOMEM;
- goto err_master_buf;
+ vme_master_free(image[i].resource);
+ goto err_master;
}
}
@@ -819,8 +820,6 @@ static int vme_user_probe(struct vme_dev *vdev)
return 0;
- /* Ensure counter set correcty to destroy all sysfs devices */
- i = VME_DEVS;
err_sysfs:
while (i > 0) {
i--;
@@ -830,12 +829,10 @@ err_sysfs:
/* Ensure counter set correcty to unalloc all master windows */
i = MASTER_MAX + 1;
-err_master_buf:
- for (i = MASTER_MINOR; i < (MASTER_MAX + 1); i++)
- kfree(image[i].kern_buf);
err_master:
while (i > MASTER_MINOR) {
i--;
+ kfree(image[i].kern_buf);
vme_master_free(image[i].resource);
}
diff --git a/drivers/staging/xgifb/vb_def.h b/drivers/staging/xgifb/vb_def.h
index 5c739bebd8a5..949f0e5eed8d 100644
--- a/drivers/staging/xgifb/vb_def.h
+++ b/drivers/staging/xgifb/vb_def.h
@@ -1,6 +1,6 @@
#ifndef _VB_DEF_
#define _VB_DEF_
-#include "../../video/sis/initdef.h"
+#include "../../video/fbdev/sis/initdef.h"
#define VB_XGI301C 0x0020 /* for 301C */
diff --git a/drivers/staging/xgifb/vb_struct.h b/drivers/staging/xgifb/vb_struct.h
index c08ff5b2d6ee..0d27594554ca 100644
--- a/drivers/staging/xgifb/vb_struct.h
+++ b/drivers/staging/xgifb/vb_struct.h
@@ -1,6 +1,6 @@
#ifndef _VB_STRUCT_
#define _VB_STRUCT_
-#include "../../video/sis/vstruct.h"
+#include "../../video/fbdev/sis/vstruct.h"
struct XGI_LVDSCRT1HDataStruct {
unsigned char Reg[8];
diff --git a/drivers/staging/xgifb/vgatypes.h b/drivers/staging/xgifb/vgatypes.h
index ddf7776c295b..264351441f99 100644
--- a/drivers/staging/xgifb/vgatypes.h
+++ b/drivers/staging/xgifb/vgatypes.h
@@ -2,8 +2,8 @@
#define _VGATYPES_
#include <linux/fb.h> /* for struct fb_var_screeninfo for sis.h */
-#include "../../video/sis/vgatypes.h"
-#include "../../video/sis/sis.h" /* for LCD_TYPE */
+#include "../../video/fbdev/sis/vgatypes.h"
+#include "../../video/fbdev/sis/sis.h" /* for LCD_TYPE */
#ifndef XGI_VB_CHIP_TYPE
enum XGI_VB_CHIP_TYPE {
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index 78cab13bbb1b..46588c85d39b 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -1593,7 +1593,9 @@ int iscsit_process_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
* Initiator is expecting a NopIN ping reply..
*/
if (hdr->itt != RESERVED_ITT) {
- BUG_ON(!cmd);
+ if (!cmd)
+ return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
+ (unsigned char *)hdr);
spin_lock_bh(&conn->cmd_lock);
list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h
index 6960f22909ae..302eb3b78715 100644
--- a/drivers/target/iscsi/iscsi_target_core.h
+++ b/drivers/target/iscsi/iscsi_target_core.h
@@ -775,6 +775,7 @@ struct iscsi_np {
int np_ip_proto;
int np_sock_type;
enum np_thread_state_table np_thread_state;
+ bool enabled;
enum iscsi_timer_flags_table np_login_timer_flags;
u32 np_exports;
enum np_flags_table np_flags;
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c
index 8739b98f6f93..ca31fa1b8a4b 100644
--- a/drivers/target/iscsi/iscsi_target_login.c
+++ b/drivers/target/iscsi/iscsi_target_login.c
@@ -436,7 +436,7 @@ static int iscsi_login_zero_tsih_s2(
}
off = mrdsl % PAGE_SIZE;
if (!off)
- return 0;
+ goto check_prot;
if (mrdsl < PAGE_SIZE)
mrdsl = PAGE_SIZE;
@@ -452,6 +452,31 @@ static int iscsi_login_zero_tsih_s2(
ISCSI_LOGIN_STATUS_NO_RESOURCES);
return -1;
}
+ /*
+ * ISER currently requires that ImmediateData + Unsolicited
+ * Data be disabled when protection / signature MRs are enabled.
+ */
+check_prot:
+ if (sess->se_sess->sup_prot_ops &
+ (TARGET_PROT_DOUT_STRIP | TARGET_PROT_DOUT_PASS |
+ TARGET_PROT_DOUT_INSERT)) {
+
+ sprintf(buf, "ImmediateData=No");
+ if (iscsi_change_param_value(buf, conn->param_list, 0) < 0) {
+ iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+ ISCSI_LOGIN_STATUS_NO_RESOURCES);
+ return -1;
+ }
+
+ sprintf(buf, "InitialR2T=Yes");
+ if (iscsi_change_param_value(buf, conn->param_list, 0) < 0) {
+ iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+ ISCSI_LOGIN_STATUS_NO_RESOURCES);
+ return -1;
+ }
+ pr_debug("Forcing ImmediateData=No + InitialR2T=Yes for"
+ " T10-PI enabled ISER session\n");
+ }
}
return 0;
@@ -984,6 +1009,7 @@ int iscsi_target_setup_login_socket(
}
np->np_transport = t;
+ np->enabled = true;
return 0;
}
diff --git a/drivers/target/iscsi/iscsi_target_tpg.c b/drivers/target/iscsi/iscsi_target_tpg.c
index eb96b20dc09e..ca1811858afd 100644
--- a/drivers/target/iscsi/iscsi_target_tpg.c
+++ b/drivers/target/iscsi/iscsi_target_tpg.c
@@ -184,6 +184,7 @@ static void iscsit_clear_tpg_np_login_thread(
return;
}
+ tpg_np->tpg_np->enabled = false;
iscsit_reset_np_thread(tpg_np->tpg_np, tpg_np, tpg, shutdown);
}
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c
index 65001e133670..26416c15d65c 100644
--- a/drivers/target/target_core_device.c
+++ b/drivers/target/target_core_device.c
@@ -798,10 +798,10 @@ int se_dev_set_emulate_write_cache(struct se_device *dev, int flag)
pr_err("emulate_write_cache not supported for pSCSI\n");
return -EINVAL;
}
- if (dev->transport->get_write_cache) {
- pr_warn("emulate_write_cache cannot be changed when underlying"
- " HW reports WriteCacheEnabled, ignoring request\n");
- return 0;
+ if (flag &&
+ dev->transport->get_write_cache) {
+ pr_err("emulate_write_cache not supported for this device\n");
+ return -EINVAL;
}
dev->dev_attrib.emulate_write_cache = flag;
@@ -936,6 +936,10 @@ int se_dev_set_pi_prot_type(struct se_device *dev, int flag)
return 0;
}
if (!dev->transport->init_prot || !dev->transport->free_prot) {
+ /* 0 is only allowed value for non-supporting backends */
+ if (flag == 0)
+ return 0;
+
pr_err("DIF protection not supported by backend: %s\n",
dev->transport->name);
return -ENOSYS;
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index d4b98690a736..789aa9eb0a1e 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -1113,6 +1113,7 @@ void transport_init_se_cmd(
init_completion(&cmd->cmd_wait_comp);
init_completion(&cmd->task_stop_comp);
spin_lock_init(&cmd->t_state_lock);
+ kref_init(&cmd->cmd_kref);
cmd->transport_state = CMD_T_DEV_ACTIVE;
cmd->se_tfo = tfo;
@@ -2357,7 +2358,6 @@ int target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd,
unsigned long flags;
int ret = 0;
- kref_init(&se_cmd->cmd_kref);
/*
* Add a second kref if the fabric caller is expecting to handle
* fabric acknowledgement that requires two target_put_sess_cmd()
diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c
index 01cf37f212c3..f5fd515b2bee 100644
--- a/drivers/target/tcm_fc/tfc_cmd.c
+++ b/drivers/target/tcm_fc/tfc_cmd.c
@@ -90,18 +90,18 @@ static void ft_free_cmd(struct ft_cmd *cmd)
{
struct fc_frame *fp;
struct fc_lport *lport;
- struct se_session *se_sess;
+ struct ft_sess *sess;
if (!cmd)
return;
- se_sess = cmd->sess->se_sess;
+ sess = cmd->sess;
fp = cmd->req_frame;
lport = fr_dev(fp);
if (fr_seq(fp))
lport->tt.seq_release(fr_seq(fp));
fc_frame_free(fp);
- percpu_ida_free(&se_sess->sess_tag_pool, cmd->se_cmd.map_tag);
- ft_sess_put(cmd->sess); /* undo get from lookup at recv */
+ percpu_ida_free(&sess->se_sess->sess_tag_pool, cmd->se_cmd.map_tag);
+ ft_sess_put(sess); /* undo get from lookup at recv */
}
void ft_release_cmd(struct se_cmd *se_cmd)
diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c
index 94f9e3a38412..0ff7fda0742f 100644
--- a/drivers/tty/hvc/hvc_console.c
+++ b/drivers/tty/hvc/hvc_console.c
@@ -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;
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index 41fe8a047d37..fe9d129c8735 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -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;
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 81f909c2101f..2d4bd3929e50 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -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;
}
@@ -1520,7 +1520,7 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
status = serial8250_rx_chars(up, status);
}
serial8250_modem_status(up);
- if (status & UART_LSR_THRE)
+ if (!up->dma && (status & UART_LSR_THRE))
serial8250_tx_chars(up);
spin_unlock_irqrestore(&port->lock, flags);
diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c
index 7046769608d4..ab9096dc3849 100644
--- a/drivers/tty/serial/8250/8250_dma.c
+++ b/drivers/tty/serial/8250/8250_dma.c
@@ -20,12 +20,15 @@ static void __dma_tx_complete(void *param)
struct uart_8250_port *p = param;
struct uart_8250_dma *dma = p->dma;
struct circ_buf *xmit = &p->port.state->xmit;
-
- dma->tx_running = 0;
+ unsigned long flags;
dma_sync_single_for_cpu(dma->txchan->device->dev, dma->tx_addr,
UART_XMIT_SIZE, DMA_TO_DEVICE);
+ spin_lock_irqsave(&p->port.lock, flags);
+
+ dma->tx_running = 0;
+
xmit->tail += dma->tx_size;
xmit->tail &= UART_XMIT_SIZE - 1;
p->port.icount.tx += dma->tx_size;
@@ -35,6 +38,8 @@ static void __dma_tx_complete(void *param)
if (!uart_circ_empty(xmit) && !uart_tx_stopped(&p->port))
serial8250_tx_dma(p);
+
+ spin_unlock_irqrestore(&p->port.lock, flags);
}
static void __dma_rx_complete(void *param)
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 2e6d8ddc4425..5d9b01aa54f4 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1226,6 +1226,7 @@ config SERIAL_BFIN_SPORT3_UART_CTSRTS
config SERIAL_TIMBERDALE
tristate "Support for timberdale UART"
select SERIAL_CORE
+ depends on X86_32 || COMPILE_TEST
---help---
Add support for UART controller on timberdale.
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index d4eda24aa68b..dacf0a09ab24 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -318,7 +318,7 @@ static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port *
.src_addr = uap->port.mapbase + UART01x_DR,
.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
.direction = DMA_DEV_TO_MEM,
- .src_maxburst = uap->fifosize >> 1,
+ .src_maxburst = uap->fifosize >> 2,
.device_fc = false,
};
@@ -2176,6 +2176,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
static int pl011_remove(struct amba_device *dev)
{
struct uart_amba_port *uap = amba_get_drvdata(dev);
+ bool busy = false;
int i;
uart_remove_one_port(&amba_reg, &uap->port);
@@ -2183,9 +2184,12 @@ static int pl011_remove(struct amba_device *dev)
for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
if (amba_ports[i] == uap)
amba_ports[i] = NULL;
+ else if (amba_ports[i])
+ busy = true;
pl011_dma_remove(uap);
- uart_unregister_driver(&amba_reg);
+ if (!busy)
+ uart_unregister_driver(&amba_reg);
return 0;
}
diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c
index 5e6fdb1ea73b..14aaea0d4131 100644
--- a/drivers/tty/serial/clps711x.c
+++ b/drivers/tty/serial/clps711x.c
@@ -368,16 +368,12 @@ static const struct uart_ops uart_clps711x_ops = {
static void uart_clps711x_console_putchar(struct uart_port *port, int ch)
{
struct clps711x_port *s = dev_get_drvdata(port->dev);
+ u32 sysflg = 0;
/* Wait for FIFO is not full */
- while (1) {
- u32 sysflg = 0;
-
+ do {
regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg);
- if (!(sysflg & SYSFLG_UTXFF))
- break;
- cond_resched();
- }
+ } while (sysflg & SYSFLG_UTXFF);
writew(ch, port->membase + UARTDR_OFFSET);
}
@@ -387,18 +383,14 @@ static void uart_clps711x_console_write(struct console *co, const char *c,
{
struct uart_port *port = clps711x_uart.state[co->index].uart_port;
struct clps711x_port *s = dev_get_drvdata(port->dev);
+ u32 sysflg = 0;
uart_console_write(port, c, n, uart_clps711x_console_putchar);
/* Wait for transmitter to become empty */
- while (1) {
- u32 sysflg = 0;
-
+ do {
regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg);
- if (!(sysflg & SYSFLG_UBUSY))
- break;
- cond_resched();
- }
+ } while (sysflg & SYSFLG_UBUSY);
}
static int uart_clps711x_console_setup(struct console *co, char *options)
diff --git a/drivers/tty/serial/efm32-uart.c b/drivers/tty/serial/efm32-uart.c
index 028582e924a5..c167a710dc39 100644
--- a/drivers/tty/serial/efm32-uart.c
+++ b/drivers/tty/serial/efm32-uart.c
@@ -798,6 +798,9 @@ static int efm32_uart_remove(struct platform_device *pdev)
static const struct of_device_id efm32_uart_dt_ids[] = {
{
+ .compatible = "energymicro,efm32-uart",
+ }, {
+ /* doesn't follow the "vendor,device" scheme, don't use */
.compatible = "efm32,uart",
}, {
/* sentinel */
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index dd8b1a5458ff..08b6b9419f0d 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -225,14 +225,19 @@ static inline void serial_omap_enable_wakeirq(struct uart_omap_port *up,
if (enable)
enable_irq(up->wakeirq);
else
- disable_irq(up->wakeirq);
+ disable_irq_nosync(up->wakeirq);
}
static void serial_omap_enable_wakeup(struct uart_omap_port *up, bool enable)
{
struct omap_uart_port_info *pdata = dev_get_platdata(up->dev);
+ if (enable == up->wakeups_enabled)
+ return;
+
serial_omap_enable_wakeirq(up, enable);
+ up->wakeups_enabled = enable;
+
if (!pdata || !pdata->enable_wakeup)
return;
@@ -1495,6 +1500,11 @@ static int serial_omap_suspend(struct device *dev)
uart_suspend_port(&serial_omap_reg, &up->port);
flush_work(&up->qos_work);
+ if (device_may_wakeup(dev))
+ serial_omap_enable_wakeup(up, true);
+ else
+ serial_omap_enable_wakeup(up, false);
+
return 0;
}
@@ -1502,6 +1512,9 @@ static int serial_omap_resume(struct device *dev)
{
struct uart_omap_port *up = dev_get_drvdata(dev);
+ if (device_may_wakeup(dev))
+ serial_omap_enable_wakeup(up, false);
+
uart_resume_port(&serial_omap_reg, &up->port);
return 0;
@@ -1789,6 +1802,7 @@ static int serial_omap_remove(struct platform_device *dev)
pm_runtime_disable(up->dev);
uart_remove_one_port(&serial_omap_reg, &up->port);
pm_qos_remove_request(&up->pm_qos_request);
+ device_init_wakeup(&dev->dev, false);
return 0;
}
@@ -1877,17 +1891,7 @@ static int serial_omap_runtime_suspend(struct device *dev)
up->context_loss_cnt = serial_omap_get_context_loss_count(up);
- if (device_may_wakeup(dev)) {
- if (!up->wakeups_enabled) {
- serial_omap_enable_wakeup(up, true);
- up->wakeups_enabled = true;
- }
- } else {
- if (up->wakeups_enabled) {
- serial_omap_enable_wakeup(up, false);
- up->wakeups_enabled = false;
- }
- }
+ serial_omap_enable_wakeup(up, true);
up->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
schedule_work(&up->qos_work);
@@ -1901,6 +1905,8 @@ static int serial_omap_runtime_resume(struct device *dev)
int loss_cnt = serial_omap_get_context_loss_count(up);
+ serial_omap_enable_wakeup(up, false);
+
if (loss_cnt < 0) {
dev_dbg(dev, "serial_omap_get_context_loss_count failed : %d\n",
loss_cnt);
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index 23f459600738..1f5505e7f90d 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -1446,8 +1446,8 @@ static int s3c24xx_serial_get_poll_char(struct uart_port *port)
static void s3c24xx_serial_put_poll_char(struct uart_port *port,
unsigned char c)
{
- unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON);
- unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON);
+ unsigned int ufcon = rd_regl(port, S3C2410_UFCON);
+ unsigned int ucon = rd_regl(port, S3C2410_UCON);
/* not possible to xmit on unconfigured port */
if (!s3c24xx_port_configured(ucon))
@@ -1455,7 +1455,7 @@ static void s3c24xx_serial_put_poll_char(struct uart_port *port,
while (!s3c24xx_serial_console_txrdy(port, ufcon))
cpu_relax();
- wr_regb(cons_uart, S3C2410_UTXH, c);
+ wr_regb(port, S3C2410_UTXH, c);
}
#endif /* CONFIG_CONSOLE_POLL */
@@ -1463,22 +1463,23 @@ static void s3c24xx_serial_put_poll_char(struct uart_port *port,
static void
s3c24xx_serial_console_putchar(struct uart_port *port, int ch)
{
- unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON);
- unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON);
-
- /* not possible to xmit on unconfigured port */
- if (!s3c24xx_port_configured(ucon))
- return;
+ unsigned int ufcon = rd_regl(port, S3C2410_UFCON);
while (!s3c24xx_serial_console_txrdy(port, ufcon))
- barrier();
- wr_regb(cons_uart, S3C2410_UTXH, ch);
+ cpu_relax();
+ wr_regb(port, S3C2410_UTXH, ch);
}
static void
s3c24xx_serial_console_write(struct console *co, const char *s,
unsigned int count)
{
+ unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON);
+
+ /* not possible to xmit on unconfigured port */
+ if (!s3c24xx_port_configured(ucon))
+ return;
+
uart_console_write(cons_uart, s, count, s3c24xx_serial_console_putchar);
}
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 2cf5649a6dc0..b68550d95a40 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -89,8 +89,7 @@ static void __uart_start(struct tty_struct *tty)
struct uart_state *state = tty->driver_data;
struct uart_port *port = state->uart_port;
- if (!uart_circ_empty(&state->xmit) && state->xmit.buf &&
- !tty->stopped && !tty->hw_stopped)
+ if (!tty->stopped && !tty->hw_stopped)
port->ops->start_tx(port);
}
@@ -138,6 +137,11 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state,
return 1;
/*
+ * Make sure the device is in D0 state.
+ */
+ uart_change_pm(state, UART_PM_STATE_ON);
+
+ /*
* Initialise and allocate the transmit and temporary
* buffer.
*/
@@ -826,25 +830,29 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
* If we fail to request resources for the
* new port, try to restore the old settings.
*/
- if (retval && old_type != PORT_UNKNOWN) {
+ if (retval) {
uport->iobase = old_iobase;
uport->type = old_type;
uport->hub6 = old_hub6;
uport->iotype = old_iotype;
uport->regshift = old_shift;
uport->mapbase = old_mapbase;
- retval = uport->ops->request_port(uport);
- /*
- * If we failed to restore the old settings,
- * we fail like this.
- */
- if (retval)
- uport->type = PORT_UNKNOWN;
- /*
- * We failed anyway.
- */
- retval = -EBUSY;
+ if (old_type != PORT_UNKNOWN) {
+ retval = uport->ops->request_port(uport);
+ /*
+ * If we failed to restore the old settings,
+ * we fail like this.
+ */
+ if (retval)
+ uport->type = PORT_UNKNOWN;
+
+ /*
+ * We failed anyway.
+ */
+ retval = -EBUSY;
+ }
+
/* Added to return the correct error -Ram Gupta */
goto exit;
}
@@ -1452,6 +1460,8 @@ static void uart_hangup(struct tty_struct *tty)
clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags);
spin_unlock_irqrestore(&port->lock, flags);
tty_port_tty_set(port, NULL);
+ if (!uart_console(state->uart_port))
+ uart_change_pm(state, UART_PM_STATE_OFF);
wake_up_interruptible(&port->open_wait);
wake_up_interruptible(&port->delta_msr_wait);
}
@@ -1570,12 +1580,6 @@ static int uart_open(struct tty_struct *tty, struct file *filp)
}
/*
- * Make sure the device is in D0 state.
- */
- if (port->count == 1)
- uart_change_pm(state, UART_PM_STATE_ON);
-
- /*
* Start up the serial port.
*/
retval = uart_startup(tty, state, 0);
diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c
index 21e6e84c0df8..dd3a96e07026 100644
--- a/drivers/tty/serial/st-asc.c
+++ b/drivers/tty/serial/st-asc.c
@@ -295,7 +295,7 @@ static void asc_receive_chars(struct uart_port *port)
status & ASC_STA_OE) {
if (c & ASC_RXBUF_FE) {
- if (c == ASC_RXBUF_FE) {
+ if (c == (ASC_RXBUF_FE | ASC_RXBUF_DUMMY_RX)) {
port->icount.brk++;
if (uart_handle_break(port))
continue;
@@ -325,7 +325,7 @@ static void asc_receive_chars(struct uart_port *port)
flag = TTY_FRAME;
}
- if (uart_handle_sysrq_char(port, c))
+ if (uart_handle_sysrq_char(port, c & 0xff))
continue;
uart_insert_char(port, c, ASC_RXBUF_DUMMY_OE, c & 0xff, flag);
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index 8ebd9f88a6f6..cf78d1985cd8 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -258,7 +258,11 @@ static int __tty_buffer_request_room(struct tty_port *port, size_t size,
n->flags = flags;
buf->tail = n;
b->commit = b->used;
- smp_mb();
+ /* 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;
} else if (change)
size = 0;
@@ -444,17 +448,24 @@ static void flush_to_ldisc(struct work_struct *work)
while (1) {
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;
+ 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)
+ if (next == NULL)
break;
- buf->head = head->next;
+ buf->head = next;
tty_buffer_free(port, head);
continue;
}
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index d3448a90f0f9..34110719fe03 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -878,9 +878,8 @@ void disassociate_ctty(int on_exit)
spin_lock_irq(&current->sighand->siglock);
put_pid(current->signal->tty_old_pgrp);
current->signal->tty_old_pgrp = NULL;
- spin_unlock_irq(&current->sighand->siglock);
- tty = get_current_tty();
+ tty = tty_kref_get(current->signal->tty);
if (tty) {
unsigned long flags;
spin_lock_irqsave(&tty->ctrl_lock, flags);
@@ -897,6 +896,7 @@ void disassociate_ctty(int on_exit)
#endif
}
+ spin_unlock_irq(&current->sighand->siglock);
/* Now clear signal->tty under the lock */
read_lock(&tasklist_lock);
session_clear_tty(task_session(current));
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index ca6831c5b763..1cd5d0ba587c 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -277,6 +277,39 @@ static void hw_phymode_configure(struct ci_hdrc *ci)
}
/**
+ * ci_usb_phy_init: initialize phy according to different phy type
+ * @ci: the controller
+ *
+ * This function returns an error code if usb_phy_init has failed
+ */
+static int ci_usb_phy_init(struct ci_hdrc *ci)
+{
+ int ret;
+
+ switch (ci->platdata->phy_mode) {
+ case USBPHY_INTERFACE_MODE_UTMI:
+ case USBPHY_INTERFACE_MODE_UTMIW:
+ case USBPHY_INTERFACE_MODE_HSIC:
+ ret = usb_phy_init(ci->transceiver);
+ if (ret)
+ return ret;
+ hw_phymode_configure(ci);
+ break;
+ case USBPHY_INTERFACE_MODE_ULPI:
+ case USBPHY_INTERFACE_MODE_SERIAL:
+ hw_phymode_configure(ci);
+ ret = usb_phy_init(ci->transceiver);
+ if (ret)
+ return ret;
+ break;
+ default:
+ ret = usb_phy_init(ci->transceiver);
+ }
+
+ return ret;
+}
+
+/**
* hw_device_reset: resets chip (execute without interruption)
* @ci: the controller
*
@@ -543,8 +576,6 @@ static int ci_hdrc_probe(struct platform_device *pdev)
return -ENODEV;
}
- hw_phymode_configure(ci);
-
if (ci->platdata->phy)
ci->transceiver = ci->platdata->phy;
else
@@ -564,7 +595,7 @@ static int ci_hdrc_probe(struct platform_device *pdev)
return -EPROBE_DEFER;
}
- ret = usb_phy_init(ci->transceiver);
+ ret = ci_usb_phy_init(ci);
if (ret) {
dev_err(dev, "unable to init phy: %d\n", ret);
return ret;
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 900f7ff805ee..904efb6035b0 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -518,13 +518,16 @@ static int acm_port_activate(struct tty_port *port, struct tty_struct *tty)
if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) {
dev_err(&acm->control->dev,
"%s - usb_submit_urb(ctrl irq) failed\n", __func__);
+ usb_autopm_put_interface(acm->control);
goto error_submit_urb;
}
acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS;
if (acm_set_control(acm, acm->ctrlout) < 0 &&
- (acm->ctrl_caps & USB_CDC_CAP_LINE))
+ (acm->ctrl_caps & USB_CDC_CAP_LINE)) {
+ usb_autopm_put_interface(acm->control);
goto error_set_control;
+ }
usb_autopm_put_interface(acm->control);
@@ -549,7 +552,6 @@ error_submit_read_urbs:
error_set_control:
usb_kill_urb(acm->ctrlurb);
error_submit_urb:
- usb_autopm_put_interface(acm->control);
error_get_interface:
disconnected:
mutex_unlock(&acm->mutex);
@@ -1652,13 +1654,27 @@ static const struct usb_device_id acm_ids[] = {
},
/* Motorola H24 HSPA module: */
{ USB_DEVICE(0x22b8, 0x2d91) }, /* modem */
- { USB_DEVICE(0x22b8, 0x2d92) }, /* modem + diagnostics */
- { USB_DEVICE(0x22b8, 0x2d93) }, /* modem + AT port */
- { USB_DEVICE(0x22b8, 0x2d95) }, /* modem + AT port + diagnostics */
- { USB_DEVICE(0x22b8, 0x2d96) }, /* modem + NMEA */
- { USB_DEVICE(0x22b8, 0x2d97) }, /* modem + diagnostics + NMEA */
- { USB_DEVICE(0x22b8, 0x2d99) }, /* modem + AT port + NMEA */
- { USB_DEVICE(0x22b8, 0x2d9a) }, /* modem + AT port + diagnostics + NMEA */
+ { USB_DEVICE(0x22b8, 0x2d92), /* modem + diagnostics */
+ .driver_info = NO_UNION_NORMAL, /* handle only modem interface */
+ },
+ { USB_DEVICE(0x22b8, 0x2d93), /* modem + AT port */
+ .driver_info = NO_UNION_NORMAL, /* handle only modem interface */
+ },
+ { USB_DEVICE(0x22b8, 0x2d95), /* modem + AT port + diagnostics */
+ .driver_info = NO_UNION_NORMAL, /* handle only modem interface */
+ },
+ { USB_DEVICE(0x22b8, 0x2d96), /* modem + NMEA */
+ .driver_info = NO_UNION_NORMAL, /* handle only modem interface */
+ },
+ { USB_DEVICE(0x22b8, 0x2d97), /* modem + diagnostics + NMEA */
+ .driver_info = NO_UNION_NORMAL, /* handle only modem interface */
+ },
+ { USB_DEVICE(0x22b8, 0x2d99), /* modem + AT port + NMEA */
+ .driver_info = NO_UNION_NORMAL, /* handle only modem interface */
+ },
+ { USB_DEVICE(0x22b8, 0x2d9a), /* modem + AT port + diagnostics + NMEA */
+ .driver_info = NO_UNION_NORMAL, /* handle only modem interface */
+ },
{ USB_DEVICE(0x0572, 0x1329), /* Hummingbird huc56s (Conexant) */
.driver_info = NO_UNION_NORMAL, /* union descriptor misplaced on
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index d59d99347d54..1f02e65fe305 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -75,7 +75,7 @@ static void for_each_companion(struct pci_dev *pdev, struct usb_hcd *hcd,
PCI_SLOT(companion->devfn) != slot)
continue;
companion_hcd = pci_get_drvdata(companion);
- if (!companion_hcd)
+ if (!companion_hcd || !companion_hcd->self.root_hub)
continue;
fn(pdev, hcd, companion, companion_hcd);
}
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index d001417e8e37..10aaaae9af25 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -821,6 +821,7 @@ static void dwc3_complete(struct device *dev)
spin_lock_irqsave(&dwc->lock, flags);
+ dwc3_event_buffers_setup(dwc);
switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL:
case USB_DR_MODE_OTG:
@@ -828,7 +829,6 @@ static void dwc3_complete(struct device *dev)
/* FALLTHROUGH */
case USB_DR_MODE_HOST:
default:
- dwc3_event_buffers_setup(dwc);
break;
}
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index a740eac74d56..70715eeededd 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -187,15 +187,12 @@ int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc)
* improve this algorithm so that we better use the internal
* FIFO space
*/
- for (num = 0; num < DWC3_ENDPOINTS_NUM; num++) {
- struct dwc3_ep *dep = dwc->eps[num];
- int fifo_number = dep->number >> 1;
+ for (num = 0; num < dwc->num_in_eps; num++) {
+ /* bit0 indicates direction; 1 means IN ep */
+ struct dwc3_ep *dep = dwc->eps[(num << 1) | 1];
int mult = 1;
int tmp;
- if (!(dep->number & 1))
- continue;
-
if (!(dep->flags & DWC3_EP_ENABLED))
continue;
@@ -224,8 +221,7 @@ int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc)
dev_vdbg(dwc->dev, "%s: Fifo Addr %04x Size %d\n",
dep->name, last_fifo_depth, fifo_size & 0xffff);
- dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(fifo_number),
- fifo_size);
+ dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(num), fifo_size);
last_fifo_depth += (fifo_size & 0xffff);
}
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index f605ad8c1902..cfd18bcca723 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -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;
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c
index 2e164dca08e8..1e12b3ee56fd 100644
--- a/drivers/usb/gadget/f_fs.c
+++ b/drivers/usb/gadget/f_fs.c
@@ -745,6 +745,12 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
*/
struct usb_gadget *gadget = epfile->ffs->gadget;
+ spin_lock_irq(&epfile->ffs->eps_lock);
+ /* In the meantime, endpoint got disabled or changed. */
+ if (epfile->ep != ep) {
+ spin_unlock_irq(&epfile->ffs->eps_lock);
+ return -ESHUTDOWN;
+ }
/*
* Controller may require buffer size to be aligned to
* maxpacketsize of an out endpoint.
@@ -752,6 +758,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
data_len = io_data->read ?
usb_ep_align_maybe(gadget, ep->ep, io_data->len) :
io_data->len;
+ spin_unlock_irq(&epfile->ffs->eps_lock);
data = kmalloc(data_len, GFP_KERNEL);
if (unlikely(!data))
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
index c11761ce5113..9a4f49dc6ac4 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -377,7 +377,7 @@ static struct sk_buff *rndis_add_header(struct gether *port,
if (skb2)
rndis_add_hdr(skb2);
- dev_kfree_skb_any(skb);
+ dev_kfree_skb(skb);
return skb2;
}
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index 15960af0f67e..a2f26cdb56fe 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -1219,6 +1219,10 @@ static int fsl_pullup(struct usb_gadget *gadget, int is_on)
struct fsl_udc *udc;
udc = container_of(gadget, struct fsl_udc, gadget);
+
+ if (!udc->vbus_active)
+ return -EOPNOTSUPP;
+
udc->softconnect = (is_on != 0);
if (can_pullup(udc))
fsl_writel((fsl_readl(&dr_regs->usbcmd) | USB_CMD_RUN_STOP),
@@ -2532,8 +2536,8 @@ static int __exit fsl_udc_remove(struct platform_device *pdev)
if (!udc_controller)
return -ENODEV;
- usb_del_gadget_udc(&udc_controller->gadget);
udc_controller->done = &done;
+ usb_del_gadget_udc(&udc_controller->gadget);
fsl_udc_clk_release();
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index b5be6f0308c2..a925d0cbcd41 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -2043,6 +2043,7 @@ gadgetfs_fill_super (struct super_block *sb, void *opts, int silent)
return -ESRCH;
/* fake probe to determine $CHIP */
+ CHIP = NULL;
usb_gadget_probe_driver(&probe_driver);
if (!CHIP)
return -ENODEV;
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index d822d822efb3..7ed452d90f4d 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -35,6 +35,7 @@
#include <asm/byteorder.h>
#include <asm/unaligned.h>
+#include "u_rndis.h"
#undef VERBOSE_DEBUG
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index 50d09c289137..b7d4f82872b7 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -48,8 +48,6 @@
#define UETH__VERSION "29-May-2008"
-#define GETHER_NAPI_WEIGHT 32
-
struct eth_dev {
/* lock is held while accessing port_usb
*/
@@ -74,7 +72,6 @@ struct eth_dev {
struct sk_buff_head *list);
struct work_struct work;
- struct napi_struct rx_napi;
unsigned long todo;
#define WORK_RX_MEMORY 0
@@ -256,16 +253,18 @@ enomem:
DBG(dev, "rx submit --> %d\n", retval);
if (skb)
dev_kfree_skb_any(skb);
+ spin_lock_irqsave(&dev->req_lock, flags);
+ list_add(&req->list, &dev->rx_reqs);
+ spin_unlock_irqrestore(&dev->req_lock, flags);
}
return retval;
}
static void rx_complete(struct usb_ep *ep, struct usb_request *req)
{
- struct sk_buff *skb = req->context;
+ struct sk_buff *skb = req->context, *skb2;
struct eth_dev *dev = ep->driver_data;
int status = req->status;
- bool rx_queue = 0;
switch (status) {
@@ -289,8 +288,30 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req)
} else {
skb_queue_tail(&dev->rx_frames, skb);
}
- if (!status)
- rx_queue = 1;
+ skb = NULL;
+
+ skb2 = skb_dequeue(&dev->rx_frames);
+ while (skb2) {
+ if (status < 0
+ || ETH_HLEN > skb2->len
+ || skb2->len > VLAN_ETH_FRAME_LEN) {
+ dev->net->stats.rx_errors++;
+ dev->net->stats.rx_length_errors++;
+ DBG(dev, "rx length %d\n", skb2->len);
+ dev_kfree_skb_any(skb2);
+ goto next_frame;
+ }
+ skb2->protocol = eth_type_trans(skb2, dev->net);
+ dev->net->stats.rx_packets++;
+ dev->net->stats.rx_bytes += skb2->len;
+
+ /* no buffer copies needed, unless hardware can't
+ * use skb buffers.
+ */
+ status = netif_rx(skb2);
+next_frame:
+ skb2 = skb_dequeue(&dev->rx_frames);
+ }
break;
/* software-driven interface shutdown */
@@ -313,20 +334,22 @@ quiesce:
/* FALLTHROUGH */
default:
- rx_queue = 1;
- dev_kfree_skb_any(skb);
dev->net->stats.rx_errors++;
DBG(dev, "rx status %d\n", status);
break;
}
+ if (skb)
+ dev_kfree_skb_any(skb);
+ if (!netif_running(dev->net)) {
clean:
spin_lock(&dev->req_lock);
list_add(&req->list, &dev->rx_reqs);
spin_unlock(&dev->req_lock);
-
- if (rx_queue && likely(napi_schedule_prep(&dev->rx_napi)))
- __napi_schedule(&dev->rx_napi);
+ req = NULL;
+ }
+ if (req)
+ rx_submit(dev, req, GFP_ATOMIC);
}
static int prealloc(struct list_head *list, struct usb_ep *ep, unsigned n)
@@ -391,24 +414,16 @@ static void rx_fill(struct eth_dev *dev, gfp_t gfp_flags)
{
struct usb_request *req;
unsigned long flags;
- int rx_counts = 0;
/* fill unused rxq slots with some skb */
spin_lock_irqsave(&dev->req_lock, flags);
while (!list_empty(&dev->rx_reqs)) {
-
- if (++rx_counts > qlen(dev->gadget, dev->qmult))
- break;
-
req = container_of(dev->rx_reqs.next,
struct usb_request, list);
list_del_init(&req->list);
spin_unlock_irqrestore(&dev->req_lock, flags);
if (rx_submit(dev, req, gfp_flags) < 0) {
- spin_lock_irqsave(&dev->req_lock, flags);
- list_add(&req->list, &dev->rx_reqs);
- spin_unlock_irqrestore(&dev->req_lock, flags);
defer_kevent(dev, WORK_RX_MEMORY);
return;
}
@@ -418,41 +433,6 @@ static void rx_fill(struct eth_dev *dev, gfp_t gfp_flags)
spin_unlock_irqrestore(&dev->req_lock, flags);
}
-static int gether_poll(struct napi_struct *napi, int budget)
-{
- struct eth_dev *dev = container_of(napi, struct eth_dev, rx_napi);
- struct sk_buff *skb;
- unsigned int work_done = 0;
- int status = 0;
-
- while ((skb = skb_dequeue(&dev->rx_frames))) {
- if (status < 0
- || ETH_HLEN > skb->len
- || skb->len > VLAN_ETH_FRAME_LEN) {
- dev->net->stats.rx_errors++;
- dev->net->stats.rx_length_errors++;
- DBG(dev, "rx length %d\n", skb->len);
- dev_kfree_skb_any(skb);
- continue;
- }
- skb->protocol = eth_type_trans(skb, dev->net);
- dev->net->stats.rx_packets++;
- dev->net->stats.rx_bytes += skb->len;
-
- status = netif_rx_ni(skb);
- }
-
- if (netif_running(dev->net)) {
- rx_fill(dev, GFP_KERNEL);
- work_done++;
- }
-
- if (work_done < budget)
- napi_complete(&dev->rx_napi);
-
- return work_done;
-}
-
static void eth_work(struct work_struct *work)
{
struct eth_dev *dev = container_of(work, struct eth_dev, work);
@@ -645,7 +625,6 @@ static void eth_start(struct eth_dev *dev, gfp_t gfp_flags)
/* and open the tx floodgates */
atomic_set(&dev->tx_qlen, 0);
netif_wake_queue(dev->net);
- napi_enable(&dev->rx_napi);
}
static int eth_open(struct net_device *net)
@@ -672,7 +651,6 @@ static int eth_stop(struct net_device *net)
unsigned long flags;
VDBG(dev, "%s\n", __func__);
- napi_disable(&dev->rx_napi);
netif_stop_queue(net);
DBG(dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n",
@@ -790,7 +768,6 @@ struct eth_dev *gether_setup_name(struct usb_gadget *g,
return ERR_PTR(-ENOMEM);
dev = netdev_priv(net);
- netif_napi_add(net, &dev->rx_napi, gether_poll, GETHER_NAPI_WEIGHT);
spin_lock_init(&dev->lock);
spin_lock_init(&dev->req_lock);
INIT_WORK(&dev->work, eth_work);
@@ -853,7 +830,6 @@ struct net_device *gether_setup_name_default(const char *netname)
return ERR_PTR(-ENOMEM);
dev = netdev_priv(net);
- netif_napi_add(net, &dev->rx_napi, gether_poll, GETHER_NAPI_WEIGHT);
spin_lock_init(&dev->lock);
spin_lock_init(&dev->req_lock);
INIT_WORK(&dev->work, eth_work);
@@ -1137,7 +1113,6 @@ void gether_disconnect(struct gether *link)
{
struct eth_dev *dev = link->ioport;
struct usb_request *req;
- struct sk_buff *skb;
WARN_ON(!dev);
if (!dev)
@@ -1164,12 +1139,6 @@ void gether_disconnect(struct gether *link)
spin_lock(&dev->req_lock);
}
spin_unlock(&dev->req_lock);
-
- spin_lock(&dev->rx_frames.lock);
- while ((skb = __skb_dequeue(&dev->rx_frames)))
- dev_kfree_skb_any(skb);
- spin_unlock(&dev->rx_frames.lock);
-
link->in_ep->driver_data = NULL;
link->in_ep->desc = NULL;
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index 9f170c53e3d9..134f354ede62 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -300,7 +300,7 @@ static int __init zero_bind(struct usb_composite_dev *cdev)
ss_opts->isoc_interval = gzero_options.isoc_interval;
ss_opts->isoc_maxpacket = gzero_options.isoc_maxpacket;
ss_opts->isoc_mult = gzero_options.isoc_mult;
- ss_opts->isoc_maxburst = gzero_options.isoc_maxpacket;
+ ss_opts->isoc_maxburst = gzero_options.isoc_maxburst;
ss_opts->bulk_buflen = gzero_options.bulk_buflen;
func_ss = usb_get_function(func_inst_ss);
diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c
index d1d8c47777c5..7f425acd9be5 100644
--- a/drivers/usb/host/ehci-exynos.c
+++ b/drivers/usb/host/ehci-exynos.c
@@ -212,6 +212,8 @@ static int exynos_ehci_suspend(struct device *dev)
int rc;
rc = ehci_suspend(hcd, do_wakeup);
+ if (rc)
+ return rc;
if (exynos_ehci->otg)
exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self);
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 6f2c8d3899d2..cf2734b532a7 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -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) &
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index b3a0e11073aa..c7dd93aad20c 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -303,6 +303,8 @@ static int ehci_platform_suspend(struct device *dev)
int ret;
ret = ehci_suspend(hcd, do_wakeup);
+ if (ret)
+ return ret;
if (pdata->power_suspend)
pdata->power_suspend(pdev);
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 27ac6ad53c3d..7ef00ecb0da1 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -509,8 +509,31 @@ static struct platform_driver tegra_ehci_driver = {
}
};
+static int tegra_ehci_reset(struct usb_hcd *hcd)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ int retval;
+ int txfifothresh;
+
+ retval = ehci_setup(hcd);
+ if (retval)
+ return retval;
+
+ /*
+ * We should really pull this value out of tegra_ehci_soc_config, but
+ * to avoid needing access to it, make use of the fact that Tegra20 is
+ * the only one so far that needs a value of 10, and Tegra20 is the
+ * only one which doesn't set has_hostpc.
+ */
+ txfifothresh = ehci->has_hostpc ? 0x10 : 10;
+ ehci_writel(ehci, txfifothresh << 16, &ehci->regs->txfill_tuning);
+
+ return 0;
+}
+
static const struct ehci_driver_overrides tegra_overrides __initconst = {
.extra_priv_size = sizeof(struct tegra_ehci_hcd),
+ .reset = tegra_ehci_reset,
};
static int __init ehci_tegra_init(void)
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index c81c8721cc5a..cd871b895013 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -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;
diff --git a/drivers/usb/host/ohci-jz4740.c b/drivers/usb/host/ohci-jz4740.c
index af8dc1b92d75..c2c221a332eb 100644
--- a/drivers/usb/host/ohci-jz4740.c
+++ b/drivers/usb/host/ohci-jz4740.c
@@ -82,14 +82,14 @@ static int ohci_jz4740_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
u16 wIndex, char *buf, u16 wLength)
{
struct jz4740_ohci_hcd *jz4740_ohci = hcd_to_jz4740_hcd(hcd);
- int ret;
+ int ret = 0;
switch (typeReq) {
- case SetHubFeature:
+ case SetPortFeature:
if (wValue == USB_PORT_FEAT_POWER)
ret = ohci_jz4740_set_vbus_power(jz4740_ohci, true);
break;
- case ClearHubFeature:
+ case ClearPortFeature:
if (wValue == USB_PORT_FEAT_POWER)
ret = ohci_jz4740_set_vbus_power(jz4740_ohci, false);
break;
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index 90879e9ccbec..bb1509675727 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -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;
}
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index 9250cada13f0..4550ce05af7f 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -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 */
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 47390e369cd4..35d447780707 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -134,6 +134,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
*/
if (pdev->subsystem_vendor == PCI_VENDOR_ID_HP)
xhci->quirks |= XHCI_SPURIOUS_WAKEUP;
+
+ xhci->quirks |= XHCI_SPURIOUS_REBOOT;
}
if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
pdev->device == PCI_DEVICE_ID_ASROCK_P67) {
@@ -143,9 +145,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
xhci->quirks |= XHCI_TRUST_TX_LENGTH;
}
if (pdev->vendor == PCI_VENDOR_ID_RENESAS &&
- pdev->device == 0x0015 &&
- pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG &&
- pdev->subsystem_device == 0xc0cd)
+ pdev->device == 0x0015)
xhci->quirks |= XHCI_RESET_ON_RESUME;
if (pdev->vendor == PCI_VENDOR_ID_VIA)
xhci->quirks |= XHCI_RESET_ON_RESUME;
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 5f926bea5ab1..7a0e3c720c00 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -550,6 +550,7 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
struct xhci_ring *ep_ring;
struct xhci_generic_trb *trb;
dma_addr_t addr;
+ u64 hw_dequeue;
ep_ring = xhci_triad_to_transfer_ring(xhci, slot_id,
ep_index, stream_id);
@@ -559,16 +560,6 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
stream_id);
return;
}
- state->new_cycle_state = 0;
- xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
- "Finding segment containing stopped TRB.");
- state->new_deq_seg = find_trb_seg(cur_td->start_seg,
- dev->eps[ep_index].stopped_trb,
- &state->new_cycle_state);
- if (!state->new_deq_seg) {
- WARN_ON(1);
- return;
- }
/* Dig out the cycle state saved by the xHC during the stop ep cmd */
xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
@@ -577,46 +568,57 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
if (ep->ep_state & EP_HAS_STREAMS) {
struct xhci_stream_ctx *ctx =
&ep->stream_info->stream_ctx_array[stream_id];
- state->new_cycle_state = 0x1 & le64_to_cpu(ctx->stream_ring);
+ hw_dequeue = le64_to_cpu(ctx->stream_ring);
} else {
struct xhci_ep_ctx *ep_ctx
= xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index);
- state->new_cycle_state = 0x1 & le64_to_cpu(ep_ctx->deq);
+ hw_dequeue = le64_to_cpu(ep_ctx->deq);
}
+ /* Find virtual address and segment of hardware dequeue pointer */
+ state->new_deq_seg = ep_ring->deq_seg;
+ state->new_deq_ptr = ep_ring->dequeue;
+ while (xhci_trb_virt_to_dma(state->new_deq_seg, state->new_deq_ptr)
+ != (dma_addr_t)(hw_dequeue & ~0xf)) {
+ next_trb(xhci, ep_ring, &state->new_deq_seg,
+ &state->new_deq_ptr);
+ if (state->new_deq_ptr == ep_ring->dequeue) {
+ WARN_ON(1);
+ return;
+ }
+ }
+ /*
+ * Find cycle state for last_trb, starting at old cycle state of
+ * hw_dequeue. If there is only one segment ring, find_trb_seg() will
+ * return immediately and cannot toggle the cycle state if this search
+ * wraps around, so add one more toggle manually in that case.
+ */
+ state->new_cycle_state = hw_dequeue & 0x1;
+ if (ep_ring->first_seg == ep_ring->first_seg->next &&
+ cur_td->last_trb < state->new_deq_ptr)
+ state->new_cycle_state ^= 0x1;
+
state->new_deq_ptr = cur_td->last_trb;
xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
"Finding segment containing last TRB in TD.");
state->new_deq_seg = find_trb_seg(state->new_deq_seg,
- state->new_deq_ptr,
- &state->new_cycle_state);
+ state->new_deq_ptr, &state->new_cycle_state);
if (!state->new_deq_seg) {
WARN_ON(1);
return;
}
+ /* Increment to find next TRB after last_trb. Cycle if appropriate. */
trb = &state->new_deq_ptr->generic;
if (TRB_TYPE_LINK_LE32(trb->field[3]) &&
(trb->field[3] & cpu_to_le32(LINK_TOGGLE)))
state->new_cycle_state ^= 0x1;
next_trb(xhci, ep_ring, &state->new_deq_seg, &state->new_deq_ptr);
- /*
- * If there is only one segment in a ring, find_trb_seg()'s while loop
- * will not run, and it will return before it has a chance to see if it
- * needs to toggle the cycle bit. It can't tell if the stalled transfer
- * ended just before the link TRB on a one-segment ring, or if the TD
- * wrapped around the top of the ring, because it doesn't have the TD in
- * question. Look for the one-segment case where stalled TRB's address
- * is greater than the new dequeue pointer address.
- */
- if (ep_ring->first_seg == ep_ring->first_seg->next &&
- state->new_deq_ptr < dev->eps[ep_index].stopped_trb)
- state->new_cycle_state ^= 0x1;
+ /* Don't update the ring cycle state for the producer (us). */
xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
"Cycle state = 0x%x", state->new_cycle_state);
- /* Don't update the ring cycle state for the producer (us). */
xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
"New dequeue segment = %p (virtual)",
state->new_deq_seg);
@@ -799,7 +801,6 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id,
if (list_empty(&ep->cancelled_td_list)) {
xhci_stop_watchdog_timer_in_irq(xhci, ep);
ep->stopped_td = NULL;
- ep->stopped_trb = NULL;
ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
return;
}
@@ -867,11 +868,9 @@ remove_finished_td:
ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
}
- /* Clear stopped_td and stopped_trb if endpoint is not halted */
- if (!(ep->ep_state & EP_HALTED)) {
+ /* Clear stopped_td if endpoint is not halted */
+ if (!(ep->ep_state & EP_HALTED))
ep->stopped_td = NULL;
- ep->stopped_trb = NULL;
- }
/*
* Drop the lock and complete the URBs in the cancelled TD list.
@@ -1941,14 +1940,12 @@ static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci,
struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index];
ep->ep_state |= EP_HALTED;
ep->stopped_td = td;
- ep->stopped_trb = event_trb;
ep->stopped_stream = stream_id;
xhci_queue_reset_ep(xhci, slot_id, ep_index);
xhci_cleanup_stalled_ring(xhci, td->urb->dev, ep_index);
ep->stopped_td = NULL;
- ep->stopped_trb = NULL;
ep->stopped_stream = 0;
xhci_ring_cmd_db(xhci);
@@ -2030,7 +2027,6 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td,
* the ring dequeue pointer or take this TD off any lists yet.
*/
ep->stopped_td = td;
- ep->stopped_trb = event_trb;
return 0;
} else {
if (trb_comp_code == COMP_STALL) {
@@ -2042,7 +2038,6 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td,
* USB class driver clear the stall later.
*/
ep->stopped_td = td;
- ep->stopped_trb = event_trb;
ep->stopped_stream = ep_ring->stream_id;
} else if (xhci_requires_manual_halt_cleanup(xhci,
ep_ctx, trb_comp_code)) {
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 8fe4e124ddd4..300836972faa 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -408,16 +408,16 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd)
#else
-static int xhci_try_enable_msi(struct usb_hcd *hcd)
+static inline int xhci_try_enable_msi(struct usb_hcd *hcd)
{
return 0;
}
-static void xhci_cleanup_msix(struct xhci_hcd *xhci)
+static inline void xhci_cleanup_msix(struct xhci_hcd *xhci)
{
}
-static void xhci_msix_sync_irqs(struct xhci_hcd *xhci)
+static inline void xhci_msix_sync_irqs(struct xhci_hcd *xhci)
{
}
@@ -2954,7 +2954,6 @@ void xhci_endpoint_reset(struct usb_hcd *hcd,
xhci_ring_cmd_db(xhci);
}
virt_ep->stopped_td = NULL;
- virt_ep->stopped_trb = NULL;
virt_ep->stopped_stream = 0;
spin_unlock_irqrestore(&xhci->lock, flags);
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index d280e9213d08..4746816aed3e 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -865,8 +865,6 @@ struct xhci_virt_ep {
#define EP_GETTING_NO_STREAMS (1 << 5)
/* ---- Related to URB cancellation ---- */
struct list_head cancelled_td_list;
- /* The TRB that was last reported in a stopped endpoint ring */
- union xhci_trb *stopped_trb;
struct xhci_td *stopped_td;
unsigned int stopped_stream;
/* Watchdog timer for stop endpoint command to cancel URBs */
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index 3372ded5def7..e2fd263585de 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -470,8 +470,9 @@ static int dsps_musb_exit(struct musb *musb)
struct dsps_glue *glue = dev_get_drvdata(dev->parent);
del_timer_sync(&glue->timer);
-
usb_phy_shutdown(musb->xceiv);
+ debugfs_remove_recursive(glue->dbgfs_root);
+
return 0;
}
@@ -708,8 +709,6 @@ static int dsps_remove(struct platform_device *pdev)
pm_runtime_put(&pdev->dev);
pm_runtime_disable(&pdev->dev);
- debugfs_remove_recursive(glue->dbgfs_root);
-
return 0;
}
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index d341c149a2f9..d369bf1f3936 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -316,7 +316,13 @@ static void omap_musb_mailbox_work(struct work_struct *mailbox_work)
{
struct omap2430_glue *glue = container_of(mailbox_work,
struct omap2430_glue, omap_musb_mailbox_work);
+ struct musb *musb = glue_to_musb(glue);
+ struct device *dev = musb->controller;
+
+ pm_runtime_get_sync(dev);
omap_musb_set_mailbox(glue);
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
}
static irqreturn_t omap2430_musb_interrupt(int irq, void *__hci)
@@ -416,6 +422,7 @@ static int omap2430_musb_init(struct musb *musb)
omap_musb_set_mailbox(glue);
phy_init(musb->phy);
+ phy_power_on(musb->phy);
pm_runtime_put_noidle(musb->controller);
return 0;
@@ -478,6 +485,7 @@ static int omap2430_musb_exit(struct musb *musb)
del_timer_sync(&musb_idle_timer);
omap2430_low_level_exit(musb);
+ phy_power_off(musb->phy);
phy_exit(musb->phy);
return 0;
diff --git a/drivers/usb/phy/phy-am335x-control.c b/drivers/usb/phy/phy-am335x-control.c
index d75196ad5f2f..35b6083b7999 100644
--- a/drivers/usb/phy/phy-am335x-control.c
+++ b/drivers/usb/phy/phy-am335x-control.c
@@ -3,6 +3,7 @@
#include <linux/err.h>
#include <linux/of.h>
#include <linux/io.h>
+#include <linux/delay.h>
#include "am35x-phy-control.h"
struct am335x_control_usb {
@@ -86,6 +87,14 @@ static void am335x_phy_power(struct phy_control *phy_ctrl, u32 id, bool on)
}
writel(val, usb_ctrl->phy_reg + reg);
+
+ /*
+ * Give the PHY ~1ms to complete the power up operation.
+ * Tests have shown unstable behaviour if other USB PHY related
+ * registers are written too shortly after such a transition.
+ */
+ if (on)
+ mdelay(1);
}
static const struct phy_control ctrl_am335x = {
diff --git a/drivers/usb/phy/phy-fsm-usb.c b/drivers/usb/phy/phy-fsm-usb.c
index c47e5a6edde2..d03fadd2629f 100644
--- a/drivers/usb/phy/phy-fsm-usb.c
+++ b/drivers/usb/phy/phy-fsm-usb.c
@@ -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:
diff --git a/drivers/usb/phy/phy.c b/drivers/usb/phy/phy.c
index 8afa813d690b..36b6bce33b20 100644
--- a/drivers/usb/phy/phy.c
+++ b/drivers/usb/phy/phy.c
@@ -132,6 +132,9 @@ struct usb_phy *usb_get_phy(enum usb_phy_type type)
if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) {
pr_debug("PHY: unable to find transceiver of type %s\n",
usb_phy_type_string(type));
+ if (!IS_ERR(phy))
+ phy = ERR_PTR(-ENODEV);
+
goto err0;
}
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index 95fa1217afdd..762e4a5f5ae9 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -104,6 +104,7 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */
{ USB_DEVICE(0x10C4, 0x822B) }, /* Modem EDGE(GSM) Comander 2 */
{ USB_DEVICE(0x10C4, 0x826B) }, /* Cygnal Integrated Products, Inc., Fasttrax GPS demonstration module */
+ { USB_DEVICE(0x10C4, 0x8281) }, /* Nanotec Plug & Drive */
{ USB_DEVICE(0x10C4, 0x8293) }, /* Telegesis ETRX2USB */
{ USB_DEVICE(0x10C4, 0x82F9) }, /* Procyon AVS */
{ USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 44ab12986805..7c6e1dedeb06 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -909,6 +909,39 @@ static const struct usb_device_id id_table_combined[] = {
{ USB_DEVICE(FTDI_VID, FTDI_Z3X_PID) },
/* Cressi Devices */
{ USB_DEVICE(FTDI_VID, FTDI_CRESSI_PID) },
+ /* Brainboxes Devices */
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_001_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_012_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_023_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_034_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_101_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_1_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_2_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_3_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_4_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_5_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_6_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_7_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_8_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_257_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_1_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_2_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_3_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_4_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_313_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_324_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_346_1_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_346_2_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_357_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_606_1_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_606_2_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_606_3_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_701_1_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_701_2_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_1_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_2_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_3_PID) },
+ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_4_PID) },
{ } /* Terminating entry */
};
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index e599fbfcde5f..993c93df6874 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -1326,3 +1326,40 @@
* Manufacturer: Cressi
*/
#define FTDI_CRESSI_PID 0x87d0
+
+/*
+ * Brainboxes devices
+ */
+#define BRAINBOXES_VID 0x05d1
+#define BRAINBOXES_VX_001_PID 0x1001 /* VX-001 ExpressCard 1 Port RS232 */
+#define BRAINBOXES_VX_012_PID 0x1002 /* VX-012 ExpressCard 2 Port RS232 */
+#define BRAINBOXES_VX_023_PID 0x1003 /* VX-023 ExpressCard 1 Port RS422/485 */
+#define BRAINBOXES_VX_034_PID 0x1004 /* VX-034 ExpressCard 2 Port RS422/485 */
+#define BRAINBOXES_US_101_PID 0x1011 /* US-101 1xRS232 */
+#define BRAINBOXES_US_324_PID 0x1013 /* US-324 1xRS422/485 1Mbaud */
+#define BRAINBOXES_US_606_1_PID 0x2001 /* US-606 6 Port RS232 Serial Port 1 and 2 */
+#define BRAINBOXES_US_606_2_PID 0x2002 /* US-606 6 Port RS232 Serial Port 3 and 4 */
+#define BRAINBOXES_US_606_3_PID 0x2003 /* US-606 6 Port RS232 Serial Port 4 and 6 */
+#define BRAINBOXES_US_701_1_PID 0x2011 /* US-701 4xRS232 1Mbaud Port 1 and 2 */
+#define BRAINBOXES_US_701_2_PID 0x2012 /* US-701 4xRS422 1Mbaud Port 3 and 4 */
+#define BRAINBOXES_US_279_1_PID 0x2021 /* US-279 8xRS422 1Mbaud Port 1 and 2 */
+#define BRAINBOXES_US_279_2_PID 0x2022 /* US-279 8xRS422 1Mbaud Port 3 and 4 */
+#define BRAINBOXES_US_279_3_PID 0x2023 /* US-279 8xRS422 1Mbaud Port 5 and 6 */
+#define BRAINBOXES_US_279_4_PID 0x2024 /* US-279 8xRS422 1Mbaud Port 7 and 8 */
+#define BRAINBOXES_US_346_1_PID 0x3011 /* US-346 4xRS422/485 1Mbaud Port 1 and 2 */
+#define BRAINBOXES_US_346_2_PID 0x3012 /* US-346 4xRS422/485 1Mbaud Port 3 and 4 */
+#define BRAINBOXES_US_257_PID 0x5001 /* US-257 2xRS232 1Mbaud */
+#define BRAINBOXES_US_313_PID 0x6001 /* US-313 2xRS422/485 1Mbaud */
+#define BRAINBOXES_US_357_PID 0x7001 /* US_357 1xRS232/422/485 */
+#define BRAINBOXES_US_842_1_PID 0x8001 /* US-842 8xRS422/485 1Mbaud Port 1 and 2 */
+#define BRAINBOXES_US_842_2_PID 0x8002 /* US-842 8xRS422/485 1Mbaud Port 3 and 4 */
+#define BRAINBOXES_US_842_3_PID 0x8003 /* US-842 8xRS422/485 1Mbaud Port 5 and 6 */
+#define BRAINBOXES_US_842_4_PID 0x8004 /* US-842 8xRS422/485 1Mbaud Port 7 and 8 */
+#define BRAINBOXES_US_160_1_PID 0x9001 /* US-160 16xRS232 1Mbaud Port 1 and 2 */
+#define BRAINBOXES_US_160_2_PID 0x9002 /* US-160 16xRS232 1Mbaud Port 3 and 4 */
+#define BRAINBOXES_US_160_3_PID 0x9003 /* US-160 16xRS232 1Mbaud Port 5 and 6 */
+#define BRAINBOXES_US_160_4_PID 0x9004 /* US-160 16xRS232 1Mbaud Port 7 and 8 */
+#define BRAINBOXES_US_160_5_PID 0x9005 /* US-160 16xRS232 1Mbaud Port 9 and 10 */
+#define BRAINBOXES_US_160_6_PID 0x9006 /* US-160 16xRS232 1Mbaud Port 11 and 12 */
+#define BRAINBOXES_US_160_7_PID 0x9007 /* US-160 16xRS232 1Mbaud Port 13 and 14 */
+#define BRAINBOXES_US_160_8_PID 0x9008 /* US-160 16xRS232 1Mbaud Port 15 and 16 */
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index a2db5be9c305..df90dae53eb9 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -28,6 +28,7 @@
#include <linux/spinlock.h>
#include <linux/mutex.h>
#include <linux/serial.h>
+#include <linux/swab.h>
#include <linux/kfifo.h>
#include <linux/ioctl.h>
#include <linux/firmware.h>
@@ -280,7 +281,7 @@ static int read_download_mem(struct usb_device *dev, int start_address,
{
int status = 0;
__u8 read_length;
- __be16 be_start_address;
+ u16 be_start_address;
dev_dbg(&dev->dev, "%s - @ %x for %d\n", __func__, start_address, length);
@@ -296,10 +297,14 @@ static int read_download_mem(struct usb_device *dev, int start_address,
if (read_length > 1) {
dev_dbg(&dev->dev, "%s - @ %x for %d\n", __func__, start_address, read_length);
}
- be_start_address = cpu_to_be16(start_address);
+ /*
+ * NOTE: Must use swab as wIndex is sent in little-endian
+ * byte order regardless of host byte order.
+ */
+ be_start_address = swab16((u16)start_address);
status = ti_vread_sync(dev, UMPC_MEMORY_READ,
(__u16)address_type,
- (__force __u16)be_start_address,
+ be_start_address,
buffer, read_length);
if (status) {
@@ -394,7 +399,7 @@ static int write_i2c_mem(struct edgeport_serial *serial,
struct device *dev = &serial->serial->dev->dev;
int status = 0;
int write_length;
- __be16 be_start_address;
+ u16 be_start_address;
/* We can only send a maximum of 1 aligned byte page at a time */
@@ -409,11 +414,16 @@ static int write_i2c_mem(struct edgeport_serial *serial,
__func__, start_address, write_length);
usb_serial_debug_data(dev, __func__, write_length, buffer);
- /* Write first page */
- be_start_address = cpu_to_be16(start_address);
+ /*
+ * Write first page.
+ *
+ * NOTE: Must use swab as wIndex is sent in little-endian byte order
+ * regardless of host byte order.
+ */
+ be_start_address = swab16((u16)start_address);
status = ti_vsend_sync(serial->serial->dev,
UMPC_MEMORY_WRITE, (__u16)address_type,
- (__force __u16)be_start_address,
+ be_start_address,
buffer, write_length);
if (status) {
dev_dbg(dev, "%s - ERROR %d\n", __func__, status);
@@ -436,11 +446,16 @@ static int write_i2c_mem(struct edgeport_serial *serial,
__func__, start_address, write_length);
usb_serial_debug_data(dev, __func__, write_length, buffer);
- /* Write next page */
- be_start_address = cpu_to_be16(start_address);
+ /*
+ * Write next page.
+ *
+ * NOTE: Must use swab as wIndex is sent in little-endian byte
+ * order regardless of host byte order.
+ */
+ be_start_address = swab16((u16)start_address);
status = ti_vsend_sync(serial->serial->dev, UMPC_MEMORY_WRITE,
(__u16)address_type,
- (__force __u16)be_start_address,
+ be_start_address,
buffer, write_length);
if (status) {
dev_err(dev, "%s - ERROR %d\n", __func__, status);
@@ -585,8 +600,8 @@ static int get_descriptor_addr(struct edgeport_serial *serial,
if (rom_desc->Type == desc_type)
return start_address;
- start_address = start_address + sizeof(struct ti_i2c_desc)
- + rom_desc->Size;
+ start_address = start_address + sizeof(struct ti_i2c_desc) +
+ le16_to_cpu(rom_desc->Size);
} while ((start_address < TI_MAX_I2C_SIZE) && rom_desc->Type);
@@ -599,7 +614,7 @@ static int valid_csum(struct ti_i2c_desc *rom_desc, __u8 *buffer)
__u16 i;
__u8 cs = 0;
- for (i = 0; i < rom_desc->Size; i++)
+ for (i = 0; i < le16_to_cpu(rom_desc->Size); i++)
cs = (__u8)(cs + buffer[i]);
if (cs != rom_desc->CheckSum) {
@@ -650,7 +665,7 @@ static int check_i2c_image(struct edgeport_serial *serial)
break;
if ((start_address + sizeof(struct ti_i2c_desc) +
- rom_desc->Size) > TI_MAX_I2C_SIZE) {
+ le16_to_cpu(rom_desc->Size)) > TI_MAX_I2C_SIZE) {
status = -ENODEV;
dev_dbg(dev, "%s - structure too big, erroring out.\n", __func__);
break;
@@ -665,7 +680,8 @@ static int check_i2c_image(struct edgeport_serial *serial)
/* Read the descriptor data */
status = read_rom(serial, start_address +
sizeof(struct ti_i2c_desc),
- rom_desc->Size, buffer);
+ le16_to_cpu(rom_desc->Size),
+ buffer);
if (status)
break;
@@ -674,7 +690,7 @@ static int check_i2c_image(struct edgeport_serial *serial)
break;
}
start_address = start_address + sizeof(struct ti_i2c_desc) +
- rom_desc->Size;
+ le16_to_cpu(rom_desc->Size);
} while ((rom_desc->Type != I2C_DESC_TYPE_ION) &&
(start_address < TI_MAX_I2C_SIZE));
@@ -712,7 +728,7 @@ static int get_manuf_info(struct edgeport_serial *serial, __u8 *buffer)
/* Read the descriptor data */
status = read_rom(serial, start_address+sizeof(struct ti_i2c_desc),
- rom_desc->Size, buffer);
+ le16_to_cpu(rom_desc->Size), buffer);
if (status)
goto exit;
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 68fc9fe65936..f213ee978516 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -234,8 +234,31 @@ static void option_instat_callback(struct urb *urb);
#define QUALCOMM_VENDOR_ID 0x05C6
#define CMOTECH_VENDOR_ID 0x16d8
-#define CMOTECH_PRODUCT_6008 0x6008
-#define CMOTECH_PRODUCT_6280 0x6280
+#define CMOTECH_PRODUCT_6001 0x6001
+#define CMOTECH_PRODUCT_CMU_300 0x6002
+#define CMOTECH_PRODUCT_6003 0x6003
+#define CMOTECH_PRODUCT_6004 0x6004
+#define CMOTECH_PRODUCT_6005 0x6005
+#define CMOTECH_PRODUCT_CGU_628A 0x6006
+#define CMOTECH_PRODUCT_CHE_628S 0x6007
+#define CMOTECH_PRODUCT_CMU_301 0x6008
+#define CMOTECH_PRODUCT_CHU_628 0x6280
+#define CMOTECH_PRODUCT_CHU_628S 0x6281
+#define CMOTECH_PRODUCT_CDU_680 0x6803
+#define CMOTECH_PRODUCT_CDU_685A 0x6804
+#define CMOTECH_PRODUCT_CHU_720S 0x7001
+#define CMOTECH_PRODUCT_7002 0x7002
+#define CMOTECH_PRODUCT_CHU_629K 0x7003
+#define CMOTECH_PRODUCT_7004 0x7004
+#define CMOTECH_PRODUCT_7005 0x7005
+#define CMOTECH_PRODUCT_CGU_629 0x7006
+#define CMOTECH_PRODUCT_CHU_629S 0x700a
+#define CMOTECH_PRODUCT_CHU_720I 0x7211
+#define CMOTECH_PRODUCT_7212 0x7212
+#define CMOTECH_PRODUCT_7213 0x7213
+#define CMOTECH_PRODUCT_7251 0x7251
+#define CMOTECH_PRODUCT_7252 0x7252
+#define CMOTECH_PRODUCT_7253 0x7253
#define TELIT_VENDOR_ID 0x1bc7
#define TELIT_PRODUCT_UC864E 0x1003
@@ -243,6 +266,7 @@ static void option_instat_callback(struct urb *urb);
#define TELIT_PRODUCT_CC864_DUAL 0x1005
#define TELIT_PRODUCT_CC864_SINGLE 0x1006
#define TELIT_PRODUCT_DE910_DUAL 0x1010
+#define TELIT_PRODUCT_UE910_V2 0x1012
#define TELIT_PRODUCT_LE920 0x1200
/* ZTE PRODUCTS */
@@ -286,6 +310,7 @@ static void option_instat_callback(struct urb *urb);
#define ALCATEL_PRODUCT_X060S_X200 0x0000
#define ALCATEL_PRODUCT_X220_X500D 0x0017
#define ALCATEL_PRODUCT_L100V 0x011e
+#define ALCATEL_PRODUCT_L800MA 0x0203
#define PIRELLI_VENDOR_ID 0x1266
#define PIRELLI_PRODUCT_C100_1 0x1002
@@ -348,6 +373,7 @@ static void option_instat_callback(struct urb *urb);
#define OLIVETTI_PRODUCT_OLICARD100 0xc000
#define OLIVETTI_PRODUCT_OLICARD145 0xc003
#define OLIVETTI_PRODUCT_OLICARD200 0xc005
+#define OLIVETTI_PRODUCT_OLICARD500 0xc00b
/* Celot products */
#define CELOT_VENDOR_ID 0x211f
@@ -501,6 +527,10 @@ static const struct option_blacklist_info huawei_cdc12_blacklist = {
.reserved = BIT(1) | BIT(2),
};
+static const struct option_blacklist_info net_intf0_blacklist = {
+ .reserved = BIT(0),
+};
+
static const struct option_blacklist_info net_intf1_blacklist = {
.reserved = BIT(1),
};
@@ -1034,13 +1064,53 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */
- { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6280) }, /* BP3-USB & BP3-EXT HSDPA */
- { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6008) },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6003),
+ .driver_info = (kernel_ulong_t)&net_intf0_blacklist },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6004) },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6005) },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CGU_628A) },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CHE_628S),
+ .driver_info = (kernel_ulong_t)&net_intf0_blacklist },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_301),
+ .driver_info = (kernel_ulong_t)&net_intf0_blacklist },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CHU_628),
+ .driver_info = (kernel_ulong_t)&net_intf0_blacklist },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CHU_628S) },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CDU_680) },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CDU_685A) },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CHU_720S),
+ .driver_info = (kernel_ulong_t)&net_intf0_blacklist },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_7002),
+ .driver_info = (kernel_ulong_t)&net_intf0_blacklist },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CHU_629K),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_7004),
+ .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_7005) },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CGU_629),
+ .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CHU_629S),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CHU_720I),
+ .driver_info = (kernel_ulong_t)&net_intf0_blacklist },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_7212),
+ .driver_info = (kernel_ulong_t)&net_intf0_blacklist },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_7213),
+ .driver_info = (kernel_ulong_t)&net_intf0_blacklist },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_7251),
+ .driver_info = (kernel_ulong_t)&net_intf1_blacklist },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_7252),
+ .driver_info = (kernel_ulong_t)&net_intf1_blacklist },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_7253),
+ .driver_info = (kernel_ulong_t)&net_intf1_blacklist },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864G) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_DUAL) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) },
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UE910_V2) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920),
.driver_info = (kernel_ulong_t)&telit_le920_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */
@@ -1498,6 +1568,8 @@ static const struct usb_device_id option_ids[] = {
.driver_info = (kernel_ulong_t)&net_intf5_blacklist },
{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_L100V),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_L800MA),
+ .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
{ USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) },
{ USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) },
{ USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14),
@@ -1543,6 +1615,9 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD200),
.driver_info = (kernel_ulong_t)&net_intf6_blacklist
},
+ { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD500),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist
+ },
{ USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */
{ USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_GT_B3730, USB_CLASS_CDC_DATA, 0x00, 0x00) }, /* Samsung GT-B3730 LTE USB modem.*/
{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM600) },
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 2e22fc22c382..b3d5a35c0d4b 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -83,6 +83,9 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) },
{ USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) },
{ USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) },
+ { USB_DEVICE(HP_VENDOR_ID, HP_LD960_PRODUCT_ID) },
+ { USB_DEVICE(HP_VENDOR_ID, HP_LCM220_PRODUCT_ID) },
+ { USB_DEVICE(HP_VENDOR_ID, HP_LCM960_PRODUCT_ID) },
{ USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) },
{ USB_DEVICE(ZEAGLE_VENDOR_ID, ZEAGLE_N2ITION3_PRODUCT_ID) },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) },
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index c38b8c00c06f..42bc082896ac 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -121,8 +121,11 @@
#define SUPERIAL_VENDOR_ID 0x5372
#define SUPERIAL_PRODUCT_ID 0x2303
-/* Hewlett-Packard LD220-HP POS Pole Display */
+/* Hewlett-Packard POS Pole Displays */
#define HP_VENDOR_ID 0x03f0
+#define HP_LD960_PRODUCT_ID 0x0b39
+#define HP_LCM220_PRODUCT_ID 0x3139
+#define HP_LCM960_PRODUCT_ID 0x3239
#define HP_LD220_PRODUCT_ID 0x3524
/* Cressi Edy (diving computer) PC interface */
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
index 968a40201e5f..6c0a542e8ec1 100644
--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -136,12 +136,36 @@ static const struct usb_device_id id_table[] = {
{USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x68a2, 0)}, /* Sierra Wireless MC7710 Device Management */
{USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x68a2, 2)}, /* Sierra Wireless MC7710 NMEA */
{USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x68a2, 3)}, /* Sierra Wireless MC7710 Modem */
+ {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x68c0, 0)}, /* Sierra Wireless MC73xx Device Management */
+ {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x68c0, 2)}, /* Sierra Wireless MC73xx NMEA */
+ {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x68c0, 3)}, /* Sierra Wireless MC73xx Modem */
{USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x901c, 0)}, /* Sierra Wireless EM7700 Device Management */
{USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x901c, 2)}, /* Sierra Wireless EM7700 NMEA */
{USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x901c, 3)}, /* Sierra Wireless EM7700 Modem */
+ {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x901f, 0)}, /* Sierra Wireless EM7355 Device Management */
+ {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x901f, 2)}, /* Sierra Wireless EM7355 NMEA */
+ {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x901f, 3)}, /* Sierra Wireless EM7355 Modem */
+ {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x9041, 0)}, /* Sierra Wireless MC7305/MC7355 Device Management */
+ {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x9041, 2)}, /* Sierra Wireless MC7305/MC7355 NMEA */
+ {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x9041, 3)}, /* Sierra Wireless MC7305/MC7355 Modem */
{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 */
};
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index a9eb6221a815..6b192e602ce0 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -291,7 +291,6 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x0f3d, 0x68A3), /* Airprime/Sierra Wireless Direct IP modems */
.driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
},
- { USB_DEVICE(0x413C, 0x08133) }, /* Dell Computer Corp. Wireless 5720 VZW Mobile Broadband (EVDO Rev-A) Minicard GPS Port */
{ }
};
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 81fc0dfcfdcf..6d40d56378d7 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -1347,10 +1347,12 @@ static int usb_serial_register(struct usb_serial_driver *driver)
static void usb_serial_deregister(struct usb_serial_driver *device)
{
pr_info("USB Serial deregistering driver %s\n", device->description);
+
mutex_lock(&table_lock);
list_del(&device->driver_list);
- usb_serial_bus_deregister(device);
mutex_unlock(&table_lock);
+
+ usb_serial_bus_deregister(device);
}
/**
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
index 640fe0173236..b078440e822f 100644
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -466,6 +466,9 @@ int usb_wwan_port_probe(struct usb_serial_port *port)
int err;
int i;
+ if (!port->bulk_in_size || !port->bulk_out_size)
+ return -ENODEV;
+
portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
if (!portdata)
return -ENOMEM;
@@ -473,9 +476,6 @@ int usb_wwan_port_probe(struct usb_serial_port *port)
init_usb_anchor(&portdata->delayed);
for (i = 0; i < N_IN_URB; i++) {
- if (!port->bulk_in_size)
- break;
-
buffer = (u8 *)__get_free_page(GFP_KERNEL);
if (!buffer)
goto bail_out_error;
@@ -489,9 +489,6 @@ int usb_wwan_port_probe(struct usb_serial_port *port)
}
for (i = 0; i < N_OUT_URB; i++) {
- if (!port->bulk_out_size)
- break;
-
buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL);
if (!buffer)
goto bail_out_error2;
diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
index 4ef2a80728f7..008d805c3d21 100644
--- a/drivers/usb/storage/shuttle_usbat.c
+++ b/drivers/usb/storage/shuttle_usbat.c
@@ -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;
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index a7ac97cc5949..511b22953167 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -137,7 +137,7 @@ static void uas_do_work(struct work_struct *work)
if (!(cmdinfo->state & IS_IN_WORK_LIST))
continue;
- err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO);
+ err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC);
if (!err)
cmdinfo->state &= ~IS_IN_WORK_LIST;
else
@@ -803,7 +803,7 @@ static int uas_eh_task_mgmt(struct scsi_cmnd *cmnd,
devinfo->running_task = 1;
memset(&devinfo->response, 0, sizeof(devinfo->response));
- sense_urb = uas_submit_sense_urb(cmnd, GFP_NOIO,
+ sense_urb = uas_submit_sense_urb(cmnd, GFP_ATOMIC,
devinfo->use_streams ? tag : 0);
if (!sense_urb) {
shost_printk(KERN_INFO, shost,
@@ -813,7 +813,7 @@ static int uas_eh_task_mgmt(struct scsi_cmnd *cmnd,
spin_unlock_irqrestore(&devinfo->lock, flags);
return FAILED;
}
- if (uas_submit_task_urb(cmnd, GFP_NOIO, function, tag)) {
+ if (uas_submit_task_urb(cmnd, GFP_ATOMIC, function, tag)) {
shost_printk(KERN_INFO, shost,
"%s: %s: submit task mgmt urb failed\n",
__func__, fname);
@@ -1030,7 +1030,7 @@ static int uas_configure_endpoints(struct uas_dev_info *devinfo)
devinfo->use_streams = 0;
} else {
devinfo->qdepth = usb_alloc_streams(devinfo->intf, eps + 1,
- 3, 256, GFP_KERNEL);
+ 3, 256, GFP_NOIO);
if (devinfo->qdepth < 0)
return devinfo->qdepth;
devinfo->use_streams = 1;
@@ -1047,7 +1047,7 @@ static void uas_free_streams(struct uas_dev_info *devinfo)
eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe);
eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe);
eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe);
- usb_free_streams(devinfo->intf, eps, 3, GFP_KERNEL);
+ usb_free_streams(devinfo->intf, eps, 3, GFP_NOIO);
}
static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)
@@ -1096,16 +1096,17 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)
if (result)
goto free_streams;
+ usb_set_intfdata(intf, shost);
result = scsi_add_host(shost, &intf->dev);
if (result)
goto free_streams;
scsi_scan_host(shost);
- usb_set_intfdata(intf, shost);
return result;
free_streams:
uas_free_streams(devinfo);
+ usb_set_intfdata(intf, NULL);
set_alt0:
usb_set_interface(udev, intf->altsetting[0].desc.bInterfaceNumber, 0);
if (shost)
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index f4a82291894a..174a447868cd 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -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",
diff --git a/drivers/usb/usb-common.c b/drivers/usb/usb-common.c
index d771870a819e..6dfd30a863c7 100644
--- a/drivers/usb/usb-common.c
+++ b/drivers/usb/usb-common.c
@@ -69,7 +69,7 @@ const char *usb_state_string(enum usb_device_state state)
[USB_STATE_RECONNECTING] = "reconnecting",
[USB_STATE_UNAUTHENTICATED] = "unauthenticated",
[USB_STATE_DEFAULT] = "default",
- [USB_STATE_ADDRESS] = "addresssed",
+ [USB_STATE_ADDRESS] = "addressed",
[USB_STATE_CONFIGURED] = "configured",
[USB_STATE_SUSPENDED] = "suspended",
};
diff --git a/drivers/usb/wusbcore/mmc.c b/drivers/usb/wusbcore/mmc.c
index 44741267c917..3f485df96226 100644
--- a/drivers/usb/wusbcore/mmc.c
+++ b/drivers/usb/wusbcore/mmc.c
@@ -301,7 +301,7 @@ int wusbhc_chid_set(struct wusbhc *wusbhc, const struct wusb_ckhdid *chid)
if (chid)
result = uwb_radio_start(&wusbhc->pal);
- else
+ else if (wusbhc->uwb_rc)
uwb_radio_stop(&wusbhc->pal);
return result;
diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index c8e2a47d62a7..3e2e4ed20157 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -2390,10 +2390,10 @@ error_complete:
done) {
dev_info(dev, "Control EP stall. Queue delayed work.\n");
- spin_lock_irq(&wa->xfer_list_lock);
+ spin_lock(&wa->xfer_list_lock);
/* move xfer from xfer_list to xfer_errored_list. */
list_move_tail(&xfer->list_node, &wa->xfer_errored_list);
- spin_unlock_irq(&wa->xfer_list_lock);
+ spin_unlock(&wa->xfer_list_lock);
spin_unlock_irqrestore(&xfer->lock, flags);
queue_work(wusbd, &wa->xfer_error_work);
} else {
diff --git a/drivers/uwb/drp.c b/drivers/uwb/drp.c
index 16ada8341c46..468c89fb6a16 100644
--- a/drivers/uwb/drp.c
+++ b/drivers/uwb/drp.c
@@ -59,6 +59,7 @@ static void uwb_rc_set_drp_cmd_done(struct uwb_rc *rc, void *arg,
struct uwb_rceb *reply, ssize_t reply_size)
{
struct uwb_rc_evt_set_drp_ie *r = (struct uwb_rc_evt_set_drp_ie *)reply;
+ unsigned long flags;
if (r != NULL) {
if (r->bResultCode != UWB_RC_RES_SUCCESS)
@@ -67,14 +68,14 @@ static void uwb_rc_set_drp_cmd_done(struct uwb_rc *rc, void *arg,
} else
dev_err(&rc->uwb_dev.dev, "SET-DRP-IE: timeout\n");
- spin_lock_irq(&rc->rsvs_lock);
+ spin_lock_irqsave(&rc->rsvs_lock, flags);
if (rc->set_drp_ie_pending > 1) {
rc->set_drp_ie_pending = 0;
- uwb_rsv_queue_update(rc);
+ uwb_rsv_queue_update(rc);
} else {
- rc->set_drp_ie_pending = 0;
+ rc->set_drp_ie_pending = 0;
}
- spin_unlock_irq(&rc->rsvs_lock);
+ spin_unlock_irqrestore(&rc->rsvs_lock, flags);
}
/**
@@ -599,8 +600,11 @@ static void uwb_drp_handle_alien_drp(struct uwb_rc *rc, struct uwb_ie_drp *drp_i
/* alloc and initialize new uwb_cnflt_alien */
cnflt = kzalloc(sizeof(struct uwb_cnflt_alien), GFP_KERNEL);
- if (!cnflt)
+ if (!cnflt) {
dev_err(dev, "failed to alloc uwb_cnflt_alien struct\n");
+ return;
+ }
+
INIT_LIST_HEAD(&cnflt->rc_node);
init_timer(&cnflt->timer);
cnflt->timer.function = uwb_cnflt_timer;
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 6c793bc683d9..c7b4f0f927b1 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -21,7 +21,15 @@ source "drivers/gpu/vga/Kconfig"
source "drivers/gpu/host1x/Kconfig"
+menu "Direct Rendering Manager"
source "drivers/gpu/drm/Kconfig"
+endmenu
+
+menu "Frame buffer Devices"
+source "drivers/video/fbdev/Kconfig"
+endmenu
+
+source "drivers/video/backlight/Kconfig"
config VGASTATE
tristate
@@ -33,2482 +41,14 @@ config VIDEOMODE_HELPERS
config HDMI
bool
-menuconfig FB
- tristate "Support for frame buffer devices"
- ---help---
- The frame buffer device provides an abstraction for the graphics
- hardware. It represents the frame buffer of some video hardware and
- allows application software to access the graphics hardware through
- a well-defined interface, so the software doesn't need to know
- anything about the low-level (hardware register) stuff.
-
- Frame buffer devices work identically across the different
- architectures supported by Linux and make the implementation of
- application programs easier and more portable; at this point, an X
- server exists which uses the frame buffer device exclusively.
- On several non-X86 architectures, the frame buffer device is the
- only way to use the graphics hardware.
-
- The device is accessed through special device nodes, usually located
- in the /dev directory, i.e. /dev/fb*.
-
- You need an utility program called fbset to make full use of frame
- buffer devices. Please read <file:Documentation/fb/framebuffer.txt>
- and the Framebuffer-HOWTO at
- <http://www.munted.org.uk/programming/Framebuffer-HOWTO-1.3.html> for more
- information.
-
- Say Y here and to the driver for your graphics board below if you
- are compiling a kernel for a non-x86 architecture.
-
- If you are compiling for the x86 architecture, you can say Y if you
- want to play with it, but it is not essential. Please note that
- running graphical applications that directly touch the hardware
- (e.g. an accelerated X server) and that are not frame buffer
- device-aware may cause unexpected results. If unsure, say N.
-
-config FIRMWARE_EDID
- bool "Enable firmware EDID"
- depends on FB
- default n
- ---help---
- This enables access to the EDID transferred from the firmware.
- On the i386, this is from the Video BIOS. Enable this if DDC/I2C
- transfers do not work for your driver and if you are using
- nvidiafb, i810fb or savagefb.
-
- In general, choosing Y for this option is safe. If you
- experience extremely long delays while booting before you get
- something on your display, try setting this to N. Matrox cards in
- combination with certain motherboards and monitors are known to
- suffer from this problem.
-
-config FB_DDC
- tristate
- depends on FB
- select I2C_ALGOBIT
- select I2C
- default n
-
-config FB_BOOT_VESA_SUPPORT
- bool
- depends on FB
- default n
- ---help---
- If true, at least one selected framebuffer driver can take advantage
- of VESA video modes set at an early boot stage via the vga= parameter.
-
-config FB_CFB_FILLRECT
- tristate
- depends on FB
- default n
- ---help---
- Include the cfb_fillrect function for generic software rectangle
- filling. This is used by drivers that don't provide their own
- (accelerated) version.
-
-config FB_CFB_COPYAREA
- tristate
- depends on FB
- default n
- ---help---
- Include the cfb_copyarea function for generic software area copying.
- This is used by drivers that don't provide their own (accelerated)
- version.
-
-config FB_CFB_IMAGEBLIT
- tristate
- depends on FB
- default n
- ---help---
- Include the cfb_imageblit function for generic software image
- blitting. This is used by drivers that don't provide their own
- (accelerated) version.
-
-config FB_CFB_REV_PIXELS_IN_BYTE
- bool
- depends on FB
- default n
- ---help---
- Allow generic frame-buffer functions to work on displays with 1, 2
- and 4 bits per pixel depths which has opposite order of pixels in
- byte order to bytes in long order.
-
-config FB_SYS_FILLRECT
- tristate
- depends on FB
- default n
- ---help---
- Include the sys_fillrect function for generic software rectangle
- filling. This is used by drivers that don't provide their own
- (accelerated) version and the framebuffer is in system RAM.
-
-config FB_SYS_COPYAREA
- tristate
- depends on FB
- default n
- ---help---
- Include the sys_copyarea function for generic software area copying.
- This is used by drivers that don't provide their own (accelerated)
- version and the framebuffer is in system RAM.
-
-config FB_SYS_IMAGEBLIT
- tristate
- depends on FB
- default n
- ---help---
- Include the sys_imageblit function for generic software image
- blitting. This is used by drivers that don't provide their own
- (accelerated) version and the framebuffer is in system RAM.
-
-menuconfig FB_FOREIGN_ENDIAN
- bool "Framebuffer foreign endianness support"
- depends on FB
- ---help---
- This menu will let you enable support for the framebuffers with
- non-native endianness (e.g. Little-Endian framebuffer on a
- Big-Endian machine). Most probably you don't have such hardware,
- so it's safe to say "n" here.
-
-choice
- prompt "Choice endianness support"
- depends on FB_FOREIGN_ENDIAN
-
-config FB_BOTH_ENDIAN
- bool "Support for Big- and Little-Endian framebuffers"
-
-config FB_BIG_ENDIAN
- bool "Support for Big-Endian framebuffers only"
-
-config FB_LITTLE_ENDIAN
- bool "Support for Little-Endian framebuffers only"
-
-endchoice
-
-config FB_SYS_FOPS
- tristate
- depends on FB
- default n
-
-config FB_DEFERRED_IO
- bool
- depends on FB
-
-config FB_HECUBA
- tristate
- depends on FB
- depends on FB_DEFERRED_IO
-
-config FB_SVGALIB
- tristate
- depends on FB
- default n
- ---help---
- Common utility functions useful to fbdev drivers of VGA-based
- cards.
-
-config FB_MACMODES
- tristate
- depends on FB
- default n
-
-config FB_BACKLIGHT
- bool
- depends on FB
- select BACKLIGHT_LCD_SUPPORT
- select BACKLIGHT_CLASS_DEVICE
- default n
-
-config FB_MODE_HELPERS
- bool "Enable Video Mode Handling Helpers"
- depends on FB
- default n
- ---help---
- This enables functions for handling video modes using the
- Generalized Timing Formula and the EDID parser. A few drivers rely
- on this feature such as the radeonfb, rivafb, and the i810fb. If
- your driver does not take advantage of this feature, choosing Y will
- just increase the kernel size by about 5K.
-
-config FB_TILEBLITTING
- bool "Enable Tile Blitting Support"
- depends on FB
- default n
- ---help---
- This enables tile blitting. Tile blitting is a drawing technique
- where the screen is divided into rectangular sections (tiles), whereas
- the standard blitting divides the screen into pixels. Because the
- default drawing element is a tile, drawing functions will be passed
- parameters in terms of number of tiles instead of number of pixels.
- For example, to draw a single character, instead of using bitmaps,
- an index to an array of bitmaps will be used. To clear or move a
- rectangular section of a screen, the rectangle will be described in
- terms of number of tiles in the x- and y-axis.
-
- This is particularly important to one driver, matroxfb. If
- unsure, say N.
-
-comment "Frame buffer hardware drivers"
- depends on FB
-
-config FB_GRVGA
- tristate "Aeroflex Gaisler framebuffer support"
- depends on FB && SPARC
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- ---help---
- This enables support for the SVGACTRL framebuffer in the GRLIB IP library from Aeroflex Gaisler.
-
-config FB_CIRRUS
- tristate "Cirrus Logic support"
- depends on FB && (ZORRO || PCI)
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- ---help---
- This enables support for Cirrus Logic GD542x/543x based boards on
- Amiga: SD64, Piccolo, Picasso II/II+, Picasso IV, or EGS Spectrum.
-
- If you have a PCI-based system, this enables support for these
- chips: GD-543x, GD-544x, GD-5480.
-
- Please read the file <file:Documentation/fb/cirrusfb.txt>.
-
- Say N unless you have such a graphics board or plan to get one
- before you next recompile the kernel.
-
-config FB_PM2
- tristate "Permedia2 support"
- depends on FB && ((AMIGA && BROKEN) || PCI)
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This is the frame buffer device driver for cards based on
- the 3D Labs Permedia, Permedia 2 and Permedia 2V chips.
- The driver was tested on the following cards:
- Diamond FireGL 1000 PRO AGP
- ELSA Gloria Synergy PCI
- Appian Jeronimo PRO (both heads) PCI
- 3DLabs Oxygen ACX aka EONtronics Picasso P2 PCI
- Techsource Raptor GFX-8P (aka Sun PGX-32) on SPARC
- ASK Graphic Blaster Exxtreme AGP
-
- To compile this driver as a module, choose M here: the
- module will be called pm2fb.
-
-config FB_PM2_FIFO_DISCONNECT
- bool "enable FIFO disconnect feature"
- depends on FB_PM2 && PCI
- help
- Support the Permedia2 FIFO disconnect feature.
-
-config FB_ARMCLCD
- tristate "ARM PrimeCell PL110 support"
- depends on ARM || ARM64 || COMPILE_TEST
- depends on FB && ARM_AMBA
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This framebuffer device driver is for the ARM PrimeCell PL110
- Colour LCD controller. ARM PrimeCells provide the building
- blocks for System on a Chip devices.
-
- If you want to compile this as a module (=code which can be
- inserted into and removed from the running kernel), say M
- here and read <file:Documentation/kbuild/modules.txt>. The module
- will be called amba-clcd.
-
-config FB_ACORN
- bool "Acorn VIDC support"
- depends on (FB = y) && ARM && ARCH_ACORN
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This is the frame buffer device driver for the Acorn VIDC graphics
- hardware found in Acorn RISC PCs and other ARM-based machines. If
- unsure, say N.
-
-config FB_CLPS711X
- bool "CLPS711X LCD support"
- depends on (FB = y) && ARM && ARCH_CLPS711X
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- Say Y to enable the Framebuffer driver for the CLPS7111 and
- EP7212 processors.
-
-config FB_SA1100
- bool "SA-1100 LCD support"
- depends on (FB = y) && ARM && ARCH_SA1100
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This is a framebuffer device for the SA-1100 LCD Controller.
- See <http://www.linux-fbdev.org/> for information on framebuffer
- devices.
-
- If you plan to use the LCD display with your SA-1100 system, say
- Y here.
-
-config FB_IMX
- tristate "Freescale i.MX1/21/25/27 LCD support"
- depends on FB && ARCH_MXC
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select FB_MODE_HELPERS
- select VIDEOMODE_HELPERS
-
-config FB_CYBER2000
- tristate "CyberPro 2000/2010/5000 support"
- depends on FB && PCI && (BROKEN || !SPARC64)
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This enables support for the Integraphics CyberPro 20x0 and 5000
- VGA chips used in the Rebel.com Netwinder and other machines.
- Say Y if you have a NetWinder or a graphics card containing this
- device, otherwise say N.
-
-config FB_CYBER2000_DDC
- bool "DDC for CyberPro support"
- depends on FB_CYBER2000
- select FB_DDC
- default y
- help
- Say Y here if you want DDC support for your CyberPro graphics
- card. This is only I2C bus support, driver does not use EDID.
-
-config FB_CYBER2000_I2C
- bool "CyberPro 2000/2010/5000 I2C support"
- depends on FB_CYBER2000 && I2C && ARCH_NETWINDER
- select I2C_ALGOBIT
- help
- Enable support for the I2C video decoder interface on the
- Integraphics CyberPro 20x0 and 5000 VGA chips. This is used
- on the Netwinder machines for the SAA7111 video capture.
-
-config FB_APOLLO
- bool
- depends on (FB = y) && APOLLO
- default y
- select FB_CFB_FILLRECT
- select FB_CFB_IMAGEBLIT
-
-config FB_Q40
- bool
- depends on (FB = y) && Q40
- default y
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
-
-config FB_AMIGA
- tristate "Amiga native chipset support"
- depends on FB && AMIGA
- help
- This is the frame buffer device driver for the builtin graphics
- chipset found in Amigas.
-
- To compile this driver as a module, choose M here: the
- module will be called amifb.
-
-config FB_AMIGA_OCS
- bool "Amiga OCS chipset support"
- depends on FB_AMIGA
- help
- This enables support for the original Agnus and Denise video chips,
- found in the Amiga 1000 and most A500's and A2000's. If you intend
- to run Linux on any of these systems, say Y; otherwise say N.
-
-config FB_AMIGA_ECS
- bool "Amiga ECS chipset support"
- depends on FB_AMIGA
- help
- This enables support for the Enhanced Chip Set, found in later
- A500's, later A2000's, the A600, the A3000, the A3000T and CDTV. If
- you intend to run Linux on any of these systems, say Y; otherwise
- say N.
-
-config FB_AMIGA_AGA
- bool "Amiga AGA chipset support"
- depends on FB_AMIGA
- help
- This enables support for the Advanced Graphics Architecture (also
- known as the AGA or AA) Chip Set, found in the A1200, A4000, A4000T
- and CD32. If you intend to run Linux on any of these systems, say Y;
- otherwise say N.
-
-config FB_FM2
- bool "Amiga FrameMaster II/Rainbow II support"
- depends on (FB = y) && ZORRO
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This is the frame buffer device driver for the Amiga FrameMaster
- card from BSC (exhibited 1992 but not shipped as a CBM product).
-
-config FB_ARC
- tristate "Arc Monochrome LCD board support"
- depends on FB && X86
- select FB_SYS_FILLRECT
- select FB_SYS_COPYAREA
- select FB_SYS_IMAGEBLIT
- select FB_SYS_FOPS
- help
- This enables support for the Arc Monochrome LCD board. The board
- is based on the KS-108 lcd controller and is typically a matrix
- of 2*n chips. This driver was tested with a 128x64 panel. This
- driver supports it for use with x86 SBCs through a 16 bit GPIO
- interface (8 bit data, 8 bit control). If you anticipate using
- this driver, say Y or M; otherwise say N. You must specify the
- GPIO IO address to be used for setting control and data.
-
-config FB_ATARI
- bool "Atari native chipset support"
- depends on (FB = y) && ATARI
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This is the frame buffer device driver for the builtin graphics
- chipset found in Ataris.
-
-config FB_OF
- bool "Open Firmware frame buffer device support"
- depends on (FB = y) && (PPC64 || PPC_OF) && (!PPC_PSERIES || PCI)
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select FB_MACMODES
- help
- Say Y if you want support with Open Firmware for your graphics
- board.
-
-config FB_CONTROL
- bool "Apple \"control\" display support"
- depends on (FB = y) && PPC_PMAC && PPC32
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select FB_MACMODES
- help
- This driver supports a frame buffer for the graphics adapter in the
- Power Macintosh 7300 and others.
-
-config FB_PLATINUM
- bool "Apple \"platinum\" display support"
- depends on (FB = y) && PPC_PMAC && PPC32
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select FB_MACMODES
- help
- This driver supports a frame buffer for the "platinum" graphics
- adapter in some Power Macintoshes.
-
-config FB_VALKYRIE
- bool "Apple \"valkyrie\" display support"
- depends on (FB = y) && (MAC || (PPC_PMAC && PPC32))
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select FB_MACMODES
- help
- This driver supports a frame buffer for the "valkyrie" graphics
- adapter in some Power Macintoshes.
-
-config FB_CT65550
- bool "Chips 65550 display support"
- depends on (FB = y) && PPC32 && PCI
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This is the frame buffer device driver for the Chips & Technologies
- 65550 graphics chip in PowerBooks.
-
-config FB_ASILIANT
- bool "Asiliant (Chips) 69000 display support"
- depends on (FB = y) && PCI
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This is the frame buffer device driver for the Asiliant 69030 chipset
-
-config FB_IMSTT
- bool "IMS Twin Turbo display support"
- depends on (FB = y) && PCI
- select FB_CFB_IMAGEBLIT
- select FB_MACMODES if PPC
- help
- The IMS Twin Turbo is a PCI-based frame buffer card bundled with
- many Macintosh and compatible computers.
-
-config FB_VGA16
- tristate "VGA 16-color graphics support"
- depends on FB && (X86 || PPC)
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select VGASTATE
- select FONT_8x16 if FRAMEBUFFER_CONSOLE
- help
- This is the frame buffer device driver for VGA 16 color graphic
- cards. Say Y if you have such a card.
-
- To compile this driver as a module, choose M here: the
- module will be called vga16fb.
-
-config FB_BF54X_LQ043
- tristate "SHARP LQ043 TFT LCD (BF548 EZKIT)"
- depends on FB && (BF54x) && !BF542
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This is the framebuffer device driver for a SHARP LQ043T1DG01 TFT LCD
-
-config FB_BFIN_T350MCQB
- tristate "Varitronix COG-T350MCQB TFT LCD display (BF527 EZKIT)"
- depends on FB && BLACKFIN
- select BFIN_GPTIMERS
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This is the framebuffer device driver for a Varitronix VL-PS-COG-T350MCQB-01 display TFT LCD
- This display is a QVGA 320x240 24-bit RGB display interfaced by an 8-bit wide PPI
- It uses PPI[0..7] PPI_FS1, PPI_FS2 and PPI_CLK.
-
-config FB_BFIN_LQ035Q1
- tristate "SHARP LQ035Q1DH02 TFT LCD"
- depends on FB && BLACKFIN && SPI
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select BFIN_GPTIMERS
- help
- This is the framebuffer device driver for a SHARP LQ035Q1DH02 TFT display found on
- the Blackfin Landscape LCD EZ-Extender Card.
- This display is a QVGA 320x240 18-bit RGB display interfaced by an 16-bit wide PPI
- It uses PPI[0..15] PPI_FS1, PPI_FS2 and PPI_CLK.
-
- To compile this driver as a module, choose M here: the
- module will be called bfin-lq035q1-fb.
-
-config FB_BF537_LQ035
- tristate "SHARP LQ035 TFT LCD (BF537 STAMP)"
- depends on FB && (BF534 || BF536 || BF537) && I2C_BLACKFIN_TWI
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select BFIN_GPTIMERS
- help
- This is the framebuffer device for a SHARP LQ035Q7DB03 TFT LCD
- attached to a BF537.
-
- To compile this driver as a module, choose M here: the
- module will be called bf537-lq035.
-
-config FB_BFIN_7393
- tristate "Blackfin ADV7393 Video encoder"
- depends on FB && BLACKFIN
- select I2C
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This is the framebuffer device for a ADV7393 video encoder
- attached to a Blackfin on the PPI port.
- If your Blackfin board has a ADV7393 select Y.
-
- To compile this driver as a module, choose M here: the
- module will be called bfin_adv7393fb.
-
-choice
- prompt "Video mode support"
- depends on FB_BFIN_7393
- default NTSC
-
-config NTSC
- bool 'NTSC 720x480'
-
-config PAL
- bool 'PAL 720x576'
-
-config NTSC_640x480
- bool 'NTSC 640x480 (Experimental)'
-
-config PAL_640x480
- bool 'PAL 640x480 (Experimental)'
-
-config NTSC_YCBCR
- bool 'NTSC 720x480 YCbCR input'
-
-config PAL_YCBCR
- bool 'PAL 720x576 YCbCR input'
-
-endchoice
-
-choice
- prompt "Size of ADV7393 frame buffer memory Single/Double Size"
- depends on (FB_BFIN_7393)
- default ADV7393_1XMEM
-
-config ADV7393_1XMEM
- bool 'Single'
-
-config ADV7393_2XMEM
- bool 'Double'
-endchoice
-
-config FB_STI
- tristate "HP STI frame buffer device support"
- depends on FB && PARISC
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select STI_CONSOLE
- select VT
- default y
- ---help---
- STI refers to the HP "Standard Text Interface" which is a set of
- BIOS routines contained in a ROM chip in HP PA-RISC based machines.
- Enabling this option will implement the linux framebuffer device
- using calls to the STI BIOS routines for initialisation.
-
- If you enable this option, you will get a planar framebuffer device
- /dev/fb which will work on the most common HP graphic cards of the
- NGLE family, including the artist chips (in the 7xx and Bxxx series),
- HCRX, HCRX24, CRX, CRX24 and VisEG series.
-
- It is safe to enable this option, so you should probably say "Y".
-
-config FB_MAC
- bool "Generic Macintosh display support"
- depends on (FB = y) && MAC
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select FB_MACMODES
-
-config FB_HP300
- bool
- depends on (FB = y) && DIO
- select FB_CFB_IMAGEBLIT
- default y
-
-config FB_TGA
- tristate "TGA/SFB+ framebuffer support"
- depends on FB && (ALPHA || TC)
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select BITREVERSE
- ---help---
- This is the frame buffer device driver for generic TGA and SFB+
- graphic cards. These include DEC ZLXp-E1, -E2 and -E3 PCI cards,
- also known as PBXGA-A, -B and -C, and DEC ZLX-E1, -E2 and -E3
- TURBOchannel cards, also known as PMAGD-A, -B and -C.
-
- Due to hardware limitations ZLX-E2 and E3 cards are not supported
- for DECstation 5000/200 systems. Additionally due to firmware
- limitations these cards may cause troubles with booting DECstation
- 5000/240 and /260 systems, but are fully supported under Linux if
- you manage to get it going. ;-)
-
- Say Y if you have one of those.
-
-config FB_UVESA
- tristate "Userspace VESA VGA graphics support"
- depends on FB && CONNECTOR
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select FB_MODE_HELPERS
- help
- This is the frame buffer driver for generic VBE 2.0 compliant
- graphic cards. It can also take advantage of VBE 3.0 features,
- such as refresh rate adjustment.
-
- This driver generally provides more features than vesafb but
- requires a userspace helper application called 'v86d'. See
- <file:Documentation/fb/uvesafb.txt> for more information.
-
- If unsure, say N.
-
-config FB_VESA
- bool "VESA VGA graphics support"
- depends on (FB = y) && X86
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select FB_BOOT_VESA_SUPPORT
- help
- This is the frame buffer device driver for generic VESA 2.0
- compliant graphic cards. The older VESA 1.2 cards are not supported.
- You will get a boot time penguin logo at no additional cost. Please
- read <file:Documentation/fb/vesafb.txt>. If unsure, say Y.
-
-config FB_EFI
- bool "EFI-based Framebuffer Support"
- depends on (FB = y) && X86 && EFI
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This is the EFI frame buffer device driver. If the firmware on
- your platform is EFI 1.10 or UEFI 2.0, select Y to add support for
- using the EFI framebuffer as your console.
-
-config FB_N411
- tristate "N411 Apollo/Hecuba devkit support"
- depends on FB && X86 && MMU
- select FB_SYS_FILLRECT
- select FB_SYS_COPYAREA
- select FB_SYS_IMAGEBLIT
- select FB_SYS_FOPS
- select FB_DEFERRED_IO
- select FB_HECUBA
- help
- This enables support for the Apollo display controller in its
- Hecuba form using the n411 devkit.
-
-config FB_HGA
- tristate "Hercules mono graphics support"
- depends on FB && X86
- help
- Say Y here if you have a Hercules mono graphics card.
-
- To compile this driver as a module, choose M here: the
- module will be called hgafb.
-
- As this card technology is at least 25 years old,
- most people will answer N here.
-
-config FB_GBE
- bool "SGI Graphics Backend frame buffer support"
- depends on (FB = y) && SGI_IP32
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This is the frame buffer device driver for SGI Graphics Backend.
- This chip is used in SGI O2 and Visual Workstation 320/540.
-
-config FB_GBE_MEM
- int "Video memory size in MB"
- depends on FB_GBE
- default 4
- help
- This is the amount of memory reserved for the framebuffer,
- which can be any value between 1MB and 8MB.
-
-config FB_SBUS
- bool "SBUS and UPA framebuffers"
- depends on (FB = y) && SPARC
- help
- Say Y if you want support for SBUS or UPA based frame buffer device.
-
-config FB_BW2
- bool "BWtwo support"
- depends on (FB = y) && (SPARC && FB_SBUS)
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This is the frame buffer device driver for the BWtwo frame buffer.
-
-config FB_CG3
- bool "CGthree support"
- depends on (FB = y) && (SPARC && FB_SBUS)
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This is the frame buffer device driver for the CGthree frame buffer.
-
-config FB_CG6
- bool "CGsix (GX,TurboGX) support"
- depends on (FB = y) && (SPARC && FB_SBUS)
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This is the frame buffer device driver for the CGsix (GX, TurboGX)
- frame buffer.
-
-config FB_FFB
- bool "Creator/Creator3D/Elite3D support"
- depends on FB_SBUS && SPARC64
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This is the frame buffer device driver for the Creator, Creator3D,
- and Elite3D graphics boards.
-
-config FB_TCX
- bool "TCX (SS4/SS5 only) support"
- depends on FB_SBUS
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This is the frame buffer device driver for the TCX 24/8bit frame
- buffer.
-
-config FB_CG14
- bool "CGfourteen (SX) support"
- depends on FB_SBUS
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This is the frame buffer device driver for the CGfourteen frame
- buffer on Desktop SPARCsystems with the SX graphics option.
-
-config FB_P9100
- bool "P9100 (Sparcbook 3 only) support"
- depends on FB_SBUS
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This is the frame buffer device driver for the P9100 card
- supported on Sparcbook 3 machines.
-
-config FB_LEO
- bool "Leo (ZX) support"
- depends on FB_SBUS
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This is the frame buffer device driver for the SBUS-based Sun ZX
- (leo) frame buffer cards.
-
-config FB_IGA
- bool "IGA 168x display support"
- depends on (FB = y) && SPARC32
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This is the framebuffer device for the INTERGRAPHICS 1680 and
- successor frame buffer cards.
-
-config FB_XVR500
- bool "Sun XVR-500 3DLABS Wildcat support"
- depends on (FB = y) && PCI && SPARC64
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This is the framebuffer device for the Sun XVR-500 and similar
- graphics cards based upon the 3DLABS Wildcat chipset. The driver
- only works on sparc64 systems where the system firmware has
- mostly initialized the card already. It is treated as a
- completely dumb framebuffer device.
-
-config FB_XVR2500
- bool "Sun XVR-2500 3DLABS Wildcat support"
- depends on (FB = y) && PCI && SPARC64
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This is the framebuffer device for the Sun XVR-2500 and similar
- graphics cards based upon the 3DLABS Wildcat chipset. The driver
- only works on sparc64 systems where the system firmware has
- mostly initialized the card already. It is treated as a
- completely dumb framebuffer device.
-
-config FB_XVR1000
- bool "Sun XVR-1000 support"
- depends on (FB = y) && SPARC64
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This is the framebuffer device for the Sun XVR-1000 and similar
- graphics cards. The driver only works on sparc64 systems where
- the system firmware has mostly initialized the card already. It
- is treated as a completely dumb framebuffer device.
-
-config FB_PVR2
- tristate "NEC PowerVR 2 display support"
- depends on FB && SH_DREAMCAST
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- ---help---
- Say Y here if you have a PowerVR 2 card in your box. If you plan to
- run linux on your Dreamcast, you will have to say Y here.
- This driver may or may not work on other PowerVR 2 cards, but is
- totally untested. Use at your own risk. If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called pvr2fb.
-
- You can pass several parameters to the driver at boot time or at
- module load time. The parameters look like "video=pvr2:XXX", where
- the meaning of XXX can be found at the end of the main source file
- (<file:drivers/video/pvr2fb.c>). Please see the file
- <file:Documentation/fb/pvr2fb.txt>.
-
-config FB_OPENCORES
- tristate "OpenCores VGA/LCD core 2.0 framebuffer support"
- depends on FB && HAS_DMA
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This enables support for the OpenCores VGA/LCD core.
-
- The OpenCores VGA/LCD core is typically used together with
- softcore CPUs (e.g. OpenRISC or Microblaze) or hard processor
- systems (e.g. Altera socfpga or Xilinx Zynq) on FPGAs.
-
- The source code and specification for the core is available at
- <http://opencores.org/project,vga_lcd>
-
-config FB_S1D13XXX
- tristate "Epson S1D13XXX framebuffer support"
- depends on FB
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- Support for S1D13XXX framebuffer device family (currently only
- working with S1D13806). Product specs at
- <http://vdc.epson.com/>
-
-config FB_ATMEL
- tristate "AT91/AT32 LCD Controller support"
- depends on FB && HAVE_FB_ATMEL
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select FB_MODE_HELPERS
- select VIDEOMODE_HELPERS
- help
- This enables support for the AT91/AT32 LCD Controller.
-
-config FB_INTSRAM
- bool "Frame Buffer in internal SRAM"
- depends on FB_ATMEL && ARCH_AT91SAM9261
- help
- Say Y if you want to map Frame Buffer in internal SRAM. Say N if you want
- to let frame buffer in external SDRAM.
-
-config FB_ATMEL_STN
- bool "Use a STN display with AT91/AT32 LCD Controller"
- depends on FB_ATMEL && (MACH_AT91SAM9261EK || MACH_AT91SAM9G10EK)
- default n
- help
- Say Y if you want to connect a STN LCD display to the AT91/AT32 LCD
- Controller. Say N if you want to connect a TFT.
-
- If unsure, say N.
-
-config FB_NVIDIA
- tristate "nVidia Framebuffer Support"
- depends on FB && PCI
- select FB_BACKLIGHT if FB_NVIDIA_BACKLIGHT
- select FB_MODE_HELPERS
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select BITREVERSE
- select VGASTATE
- help
- This driver supports graphics boards with the nVidia chips, TNT
- and newer. For very old chipsets, such as the RIVA128, then use
- the rivafb.
- Say Y if you have such a graphics board.
-
- To compile this driver as a module, choose M here: the
- module will be called nvidiafb.
-
-config FB_NVIDIA_I2C
- bool "Enable DDC Support"
- depends on FB_NVIDIA
- select FB_DDC
- help
- This enables I2C support for nVidia Chipsets. This is used
- only for getting EDID information from the attached display
- allowing for robust video mode handling and switching.
-
- Because fbdev-2.6 requires that drivers must be able to
- independently validate video mode parameters, you should say Y
- here.
-
-config FB_NVIDIA_DEBUG
- bool "Lots of debug output"
- depends on FB_NVIDIA
- default n
- help
- Say Y here if you want the nVidia driver to output all sorts
- of debugging information to provide to the maintainer when
- something goes wrong.
-
-config FB_NVIDIA_BACKLIGHT
- bool "Support for backlight control"
- depends on FB_NVIDIA
- default y
- help
- Say Y here if you want to control the backlight of your display.
-
-config FB_RIVA
- tristate "nVidia Riva support"
- depends on FB && PCI
- select FB_BACKLIGHT if FB_RIVA_BACKLIGHT
- select FB_MODE_HELPERS
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select BITREVERSE
- select VGASTATE
- help
- This driver supports graphics boards with the nVidia Riva/Geforce
- chips.
- Say Y if you have such a graphics board.
-
- To compile this driver as a module, choose M here: the
- module will be called rivafb.
-
-config FB_RIVA_I2C
- bool "Enable DDC Support"
- depends on FB_RIVA
- select FB_DDC
- help
- This enables I2C support for nVidia Chipsets. This is used
- only for getting EDID information from the attached display
- allowing for robust video mode handling and switching.
-
- Because fbdev-2.6 requires that drivers must be able to
- independently validate video mode parameters, you should say Y
- here.
-
-config FB_RIVA_DEBUG
- bool "Lots of debug output"
- depends on FB_RIVA
- default n
- help
- Say Y here if you want the Riva driver to output all sorts
- of debugging information to provide to the maintainer when
- something goes wrong.
-
-config FB_RIVA_BACKLIGHT
- bool "Support for backlight control"
- depends on FB_RIVA
- default y
- help
- Say Y here if you want to control the backlight of your display.
-
-config FB_I740
- tristate "Intel740 support"
- depends on FB && PCI
- select FB_MODE_HELPERS
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select VGASTATE
- select FB_DDC
- help
- This driver supports graphics cards based on Intel740 chip.
-
-config FB_I810
- tristate "Intel 810/815 support"
- depends on FB && PCI && X86_32 && AGP_INTEL
- select FB_MODE_HELPERS
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select VGASTATE
- help
- This driver supports the on-board graphics built in to the Intel 810
- and 815 chipsets. Say Y if you have and plan to use such a board.
-
- To compile this driver as a module, choose M here: the
- module will be called i810fb.
-
- For more information, please read
- <file:Documentation/fb/intel810.txt>
-
-config FB_I810_GTF
- bool "use VESA Generalized Timing Formula"
- depends on FB_I810
- help
- If you say Y, then the VESA standard, Generalized Timing Formula
- or GTF, will be used to calculate the required video timing values
- per video mode. Since the GTF allows nondiscrete timings
- (nondiscrete being a range of values as opposed to discrete being a
- set of values), you'll be able to use any combination of horizontal
- and vertical resolutions, and vertical refresh rates without having
- to specify your own timing parameters. This is especially useful
- to maximize the performance of an aging display, or if you just
- have a display with nonstandard dimensions. A VESA compliant
- monitor is recommended, but can still work with non-compliant ones.
- If you need or want this, then select this option. The timings may
- not be compliant with Intel's recommended values. Use at your own
- risk.
-
- If you say N, the driver will revert to discrete video timings
- using a set recommended by Intel in their documentation.
-
- If unsure, say N.
-
-config FB_I810_I2C
- bool "Enable DDC Support"
- depends on FB_I810 && FB_I810_GTF
- select FB_DDC
- help
-
-config FB_LE80578
- tristate "Intel LE80578 (Vermilion) support"
- depends on FB && PCI && X86
- select FB_MODE_HELPERS
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This driver supports the LE80578 (Vermilion Range) chipset
-
-config FB_CARILLO_RANCH
- tristate "Intel Carillo Ranch support"
- depends on FB_LE80578 && FB && PCI && X86
- help
- This driver supports the LE80578 (Carillo Ranch) board
-
-config FB_INTEL
- tristate "Intel 830M/845G/852GM/855GM/865G/915G/945G/945GM/965G/965GM support"
- depends on FB && PCI && X86 && AGP_INTEL && EXPERT
- select FB_MODE_HELPERS
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select FB_BOOT_VESA_SUPPORT if FB_INTEL = y
- depends on !DRM_I915
- help
- This driver supports the on-board graphics built in to the Intel
- 830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/965G/965GM chipsets.
- Say Y if you have and plan to use such a board.
-
- To make FB_INTELFB=Y work you need to say AGP_INTEL=y too.
-
- To compile this driver as a module, choose M here: the
- module will be called intelfb.
-
- For more information, please read <file:Documentation/fb/intelfb.txt>
-
-config FB_INTEL_DEBUG
- bool "Intel driver Debug Messages"
- depends on FB_INTEL
- ---help---
- Say Y here if you want the Intel driver to output all sorts
- of debugging information to provide to the maintainer when
- something goes wrong.
-
-config FB_INTEL_I2C
- bool "DDC/I2C for Intel framebuffer support"
- depends on FB_INTEL
- select FB_DDC
- default y
- help
- Say Y here if you want DDC/I2C support for your on-board Intel graphics.
-
-config FB_MATROX
- tristate "Matrox acceleration"
- depends on FB && PCI
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select FB_TILEBLITTING
- select FB_MACMODES if PPC_PMAC
- ---help---
- Say Y here if you have a Matrox Millennium, Matrox Millennium II,
- Matrox Mystique, Matrox Mystique 220, Matrox Productiva G100, Matrox
- Mystique G200, Matrox Millennium G200, Matrox Marvel G200 video,
- Matrox G400, G450 or G550 card in your box.
-
- To compile this driver as a module, choose M here: the
- module will be called matroxfb.
-
- You can pass several parameters to the driver at boot time or at
- module load time. The parameters look like "video=matroxfb:XXX", and
- are described in <file:Documentation/fb/matroxfb.txt>.
-
-config FB_MATROX_MILLENIUM
- bool "Millennium I/II support"
- depends on FB_MATROX
- help
- Say Y here if you have a Matrox Millennium or Matrox Millennium II
- video card. If you select "Advanced lowlevel driver options" below,
- you should check 4 bpp packed pixel, 8 bpp packed pixel, 16 bpp
- packed pixel, 24 bpp packed pixel and 32 bpp packed pixel. You can
- also use font widths different from 8.
-
-config FB_MATROX_MYSTIQUE
- bool "Mystique support"
- depends on FB_MATROX
- help
- Say Y here if you have a Matrox Mystique or Matrox Mystique 220
- video card. If you select "Advanced lowlevel driver options" below,
- you should check 8 bpp packed pixel, 16 bpp packed pixel, 24 bpp
- packed pixel and 32 bpp packed pixel. You can also use font widths
- different from 8.
-
-config FB_MATROX_G
- bool "G100/G200/G400/G450/G550 support"
- depends on FB_MATROX
- ---help---
- Say Y here if you have a Matrox G100, G200, G400, G450 or G550 based
- video card. If you select "Advanced lowlevel driver options", you
- should check 8 bpp packed pixel, 16 bpp packed pixel, 24 bpp packed
- pixel and 32 bpp packed pixel. You can also use font widths
- different from 8.
-
- If you need support for G400 secondary head, you must say Y to
- "Matrox I2C support" and "G400 second head support" right below.
- G450/G550 secondary head and digital output are supported without
- additional modules.
-
- The driver starts in monitor mode. You must use the matroxset tool
- (available at <ftp://platan.vc.cvut.cz/pub/linux/matrox-latest/>) to
- swap primary and secondary head outputs, or to change output mode.
- Secondary head driver always start in 640x480 resolution and you
- must use fbset to change it.
-
- Do not forget that second head supports only 16 and 32 bpp
- packed pixels, so it is a good idea to compile them into the kernel
- too. You can use only some font widths, as the driver uses generic
- painting procedures (the secondary head does not use acceleration
- engine).
-
- G450/G550 hardware can display TV picture only from secondary CRTC,
- and it performs no scaling, so picture must have 525 or 625 lines.
-
-config FB_MATROX_I2C
- tristate "Matrox I2C support"
- depends on FB_MATROX
- select FB_DDC
- ---help---
- This drivers creates I2C buses which are needed for accessing the
- DDC (I2C) bus present on all Matroxes, an I2C bus which
- interconnects Matrox optional devices, like MGA-TVO on G200 and
- G400, and the secondary head DDC bus, present on G400 only.
-
- You can say Y or M here if you want to experiment with monitor
- detection code. You must say Y or M here if you want to use either
- second head of G400 or MGA-TVO on G200 or G400.
-
- If you compile it as module, it will create a module named
- i2c-matroxfb.
-
-config FB_MATROX_MAVEN
- tristate "G400 second head support"
- depends on FB_MATROX_G && FB_MATROX_I2C
- ---help---
- WARNING !!! This support does not work with G450 !!!
-
- Say Y or M here if you want to use a secondary head (meaning two
- monitors in parallel) on G400 or MGA-TVO add-on on G200. Secondary
- head is not compatible with accelerated XFree 3.3.x SVGA servers -
- secondary head output is blanked while you are in X. With XFree
- 3.9.17 preview you can use both heads if you use SVGA over fbdev or
- the fbdev driver on first head and the fbdev driver on second head.
-
- If you compile it as module, two modules are created,
- matroxfb_crtc2 and matroxfb_maven. Matroxfb_maven is needed for
- both G200 and G400, matroxfb_crtc2 is needed only by G400. You must
- also load i2c-matroxfb to get it to run.
-
- The driver starts in monitor mode and you must use the matroxset
- tool (available at
- <ftp://platan.vc.cvut.cz/pub/linux/matrox-latest/>) to switch it to
- PAL or NTSC or to swap primary and secondary head outputs.
- Secondary head driver also always start in 640x480 resolution, you
- must use fbset to change it.
-
- Also do not forget that second head supports only 16 and 32 bpp
- packed pixels, so it is a good idea to compile them into the kernel
- too. You can use only some font widths, as the driver uses generic
- painting procedures (the secondary head does not use acceleration
- engine).
-
-config FB_RADEON
- tristate "ATI Radeon display support"
- depends on FB && PCI
- select FB_BACKLIGHT if FB_RADEON_BACKLIGHT
- select FB_MODE_HELPERS
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select FB_MACMODES if PPC_OF
- help
- Choose this option if you want to use an ATI Radeon graphics card as
- a framebuffer device. There are both PCI and AGP versions. You
- don't need to choose this to run the Radeon in plain VGA mode.
-
- There is a product page at
- http://products.amd.com/en-us/GraphicCardResult.aspx
-
-config FB_RADEON_I2C
- bool "DDC/I2C for ATI Radeon support"
- depends on FB_RADEON
- select FB_DDC
- default y
- help
- Say Y here if you want DDC/I2C support for your Radeon board.
-
-config FB_RADEON_BACKLIGHT
- bool "Support for backlight control"
- depends on FB_RADEON
- default y
- help
- Say Y here if you want to control the backlight of your display.
-
-config FB_RADEON_DEBUG
- bool "Lots of debug output from Radeon driver"
- depends on FB_RADEON
- default n
- help
- Say Y here if you want the Radeon driver to output all sorts
- of debugging information to provide to the maintainer when
- something goes wrong.
-
-config FB_ATY128
- tristate "ATI Rage128 display support"
- depends on FB && PCI
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select FB_BACKLIGHT if FB_ATY128_BACKLIGHT
- select FB_MACMODES if PPC_PMAC
- help
- This driver supports graphics boards with the ATI Rage128 chips.
- Say Y if you have such a graphics board and read
- <file:Documentation/fb/aty128fb.txt>.
-
- To compile this driver as a module, choose M here: the
- module will be called aty128fb.
-
-config FB_ATY128_BACKLIGHT
- bool "Support for backlight control"
- depends on FB_ATY128
- default y
- help
- Say Y here if you want to control the backlight of your display.
-
-config FB_ATY
- tristate "ATI Mach64 display support" if PCI || ATARI
- depends on FB && !SPARC32
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select FB_BACKLIGHT if FB_ATY_BACKLIGHT
- select FB_MACMODES if PPC
- help
- This driver supports graphics boards with the ATI Mach64 chips.
- Say Y if you have such a graphics board.
-
- To compile this driver as a module, choose M here: the
- module will be called atyfb.
-
-config FB_ATY_CT
- bool "Mach64 CT/VT/GT/LT (incl. 3D RAGE) support"
- depends on PCI && FB_ATY
- default y if SPARC64 && PCI
- help
- Say Y here to support use of ATI's 64-bit Rage boards (or other
- boards based on the Mach64 CT, VT, GT, and LT chipsets) as a
- framebuffer device. The ATI product support page for these boards
- is at <http://support.ati.com/products/pc/mach64/mach64.html>.
-
-config FB_ATY_GENERIC_LCD
- bool "Mach64 generic LCD support"
- depends on FB_ATY_CT
- help
- Say Y if you have a laptop with an ATI Rage LT PRO, Rage Mobility,
- Rage XC, or Rage XL chipset.
-
-config FB_ATY_GX
- bool "Mach64 GX support" if PCI
- depends on FB_ATY
- default y if ATARI
- help
- Say Y here to support use of the ATI Mach64 Graphics Expression
- board (or other boards based on the Mach64 GX chipset) as a
- framebuffer device. The ATI product support page for these boards
- is at
- <http://support.ati.com/products/pc/mach64/graphics_xpression.html>.
-
-config FB_ATY_BACKLIGHT
- bool "Support for backlight control"
- depends on FB_ATY
- default y
- help
- Say Y here if you want to control the backlight of your display.
-
-config FB_S3
- tristate "S3 Trio/Virge support"
- depends on FB && PCI
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select FB_TILEBLITTING
- select FB_SVGALIB
- select VGASTATE
- select FONT_8x16 if FRAMEBUFFER_CONSOLE
- ---help---
- Driver for graphics boards with S3 Trio / S3 Virge chip.
-
-config FB_S3_DDC
- bool "DDC for S3 support"
- depends on FB_S3
- select FB_DDC
- default y
- help
- Say Y here if you want DDC support for your S3 graphics card.
-
-config FB_SAVAGE
- tristate "S3 Savage support"
- depends on FB && PCI
- select FB_MODE_HELPERS
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select VGASTATE
- help
- This driver supports notebooks and computers with S3 Savage PCI/AGP
- chips.
-
- Say Y if you have such a graphics card.
-
- To compile this driver as a module, choose M here; the module
- will be called savagefb.
-
-config FB_SAVAGE_I2C
- bool "Enable DDC2 Support"
- depends on FB_SAVAGE
- select FB_DDC
- help
- This enables I2C support for S3 Savage Chipsets. This is used
- only for getting EDID information from the attached display
- allowing for robust video mode handling and switching.
-
- Because fbdev-2.6 requires that drivers must be able to
- independently validate video mode parameters, you should say Y
- here.
-
-config FB_SAVAGE_ACCEL
- bool "Enable Console Acceleration"
- depends on FB_SAVAGE
- default n
- help
- This option will compile in console acceleration support. If
- the resulting framebuffer console has bothersome glitches, then
- choose N here.
-
-config FB_SIS
- tristate "SiS/XGI display support"
- depends on FB && PCI
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select FB_BOOT_VESA_SUPPORT if FB_SIS = y
- help
- This is the frame buffer device driver for the SiS 300, 315, 330
- and 340 series as well as XGI V3XT, V5, V8, Z7 graphics chipsets.
- Specs available at <http://www.sis.com> and <http://www.xgitech.com>.
-
- To compile this driver as a module, choose M here; the module
- will be called sisfb.
-
-config FB_SIS_300
- bool "SiS 300 series support"
- depends on FB_SIS
- help
- Say Y here to support use of the SiS 300/305, 540, 630 and 730.
-
-config FB_SIS_315
- bool "SiS 315/330/340 series and XGI support"
- depends on FB_SIS
- help
- Say Y here to support use of the SiS 315, 330 and 340 series
- (315/H/PRO, 55x, 650, 651, 740, 330, 661, 741, 760, 761) as well
- as XGI V3XT, V5, V8 and Z7.
-
-config FB_VIA
- tristate "VIA UniChrome (Pro) and Chrome9 display support"
- depends on FB && PCI && X86
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select I2C_ALGOBIT
- select I2C
- select GPIOLIB
- help
- This is the frame buffer device driver for Graphics chips of VIA
- UniChrome (Pro) Family (CLE266,PM800/CN400,P4M800CE/P4M800Pro/
- CN700/VN800,CX700/VX700,P4M890) and Chrome9 Family (K8M890,CN896
- /P4M900,VX800)
- Say Y if you have a VIA UniChrome graphics board.
-
- To compile this driver as a module, choose M here: the
- module will be called viafb.
-
-if FB_VIA
-
-config FB_VIA_DIRECT_PROCFS
- bool "direct hardware access via procfs (DEPRECATED)(DANGEROUS)"
- depends on FB_VIA
- default n
- help
- Allow direct hardware access to some output registers via procfs.
- This is dangerous but may provide the only chance to get the
- correct output device configuration.
- Its use is strongly discouraged.
-
-config FB_VIA_X_COMPATIBILITY
- bool "X server compatibility"
- depends on FB_VIA
- default n
- help
- This option reduces the functionality (power saving, ...) of the
- framebuffer to avoid negative impact on the OpenChrome X server.
- If you use any X server other than fbdev you should enable this
- otherwise it should be safe to disable it and allow using all
- features.
-
-endif
-
-config FB_NEOMAGIC
- tristate "NeoMagic display support"
- depends on FB && PCI
- select FB_MODE_HELPERS
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select VGASTATE
- help
- This driver supports notebooks with NeoMagic PCI chips.
- Say Y if you have such a graphics card.
-
- To compile this driver as a module, choose M here: the
- module will be called neofb.
-
-config FB_KYRO
- tristate "IMG Kyro support"
- depends on FB && PCI
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- Say Y here if you have a STG4000 / Kyro / PowerVR 3 based
- graphics board.
-
- To compile this driver as a module, choose M here: the
- module will be called kyrofb.
-
-config FB_3DFX
- tristate "3Dfx Banshee/Voodoo3/Voodoo5 display support"
- depends on FB && PCI
- select FB_CFB_IMAGEBLIT
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_MODE_HELPERS
- help
- This driver supports graphics boards with the 3Dfx Banshee,
- Voodoo3 or VSA-100 (aka Voodoo4/5) chips. Say Y if you have
- such a graphics board.
-
- To compile this driver as a module, choose M here: the
- module will be called tdfxfb.
-
-config FB_3DFX_ACCEL
- bool "3Dfx Acceleration functions"
- depends on FB_3DFX
- ---help---
- This will compile the 3Dfx Banshee/Voodoo3/VSA-100 frame buffer
- device driver with acceleration functions.
-
-config FB_3DFX_I2C
- bool "Enable DDC/I2C support"
- depends on FB_3DFX
- select FB_DDC
- default y
- help
- Say Y here if you want DDC/I2C support for your 3dfx Voodoo3.
-
-config FB_VOODOO1
- tristate "3Dfx Voodoo Graphics (sst1) support"
- depends on FB && PCI
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- ---help---
- Say Y here if you have a 3Dfx Voodoo Graphics (Voodoo1/sst1) or
- Voodoo2 (cvg) based graphics card.
-
- To compile this driver as a module, choose M here: the
- module will be called sstfb.
-
- WARNING: Do not use any application that uses the 3D engine
- (namely glide) while using this driver.
- Please read the <file:Documentation/fb/sstfb.txt> for supported
- options and other important info support.
-
-config FB_VT8623
- tristate "VIA VT8623 support"
- depends on FB && PCI
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select FB_TILEBLITTING
- select FB_SVGALIB
- select VGASTATE
- select FONT_8x16 if FRAMEBUFFER_CONSOLE
- ---help---
- Driver for CastleRock integrated graphics core in the
- VIA VT8623 [Apollo CLE266] chipset.
-
-config FB_TRIDENT
- tristate "Trident/CyberXXX/CyberBlade support"
- depends on FB && PCI
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- ---help---
- This is the frame buffer device driver for Trident PCI/AGP chipsets.
- Supported chipset families are TGUI 9440/96XX, 3DImage, Blade3D
- and Blade XP.
- There are also integrated versions of these chips called CyberXXXX,
- CyberImage or CyberBlade. These chips are mostly found in laptops
- but also on some motherboards including early VIA EPIA motherboards.
- For more information, read <file:Documentation/fb/tridentfb.txt>
-
- Say Y if you have such a graphics board.
-
- To compile this driver as a module, choose M here: the
- module will be called tridentfb.
-
-config FB_ARK
- tristate "ARK 2000PV support"
- depends on FB && PCI
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select FB_TILEBLITTING
- select FB_SVGALIB
- select VGASTATE
- select FONT_8x16 if FRAMEBUFFER_CONSOLE
- ---help---
- Driver for PCI graphics boards with ARK 2000PV chip
- and ICS 5342 RAMDAC.
-
-config FB_PM3
- tristate "Permedia3 support"
- depends on FB && PCI
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This is the frame buffer device driver for the 3DLabs Permedia3
- chipset, used in Formac ProFormance III, 3DLabs Oxygen VX1 &
- similar boards, 3DLabs Permedia3 Create!, Appian Jeronimo 2000
- and maybe other boards.
-
-config FB_CARMINE
- tristate "Fujitsu carmine frame buffer support"
- depends on FB && PCI
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This is the frame buffer device driver for the Fujitsu Carmine chip.
- The driver provides two independent frame buffer devices.
-
-choice
- depends on FB_CARMINE
- prompt "DRAM timing"
- default FB_CARMINE_DRAM_EVAL
-
-config FB_CARMINE_DRAM_EVAL
- bool "Eval board timings"
- help
- Use timings which work on the eval card.
-
-config CARMINE_DRAM_CUSTOM
- bool "Custom board timings"
- help
- Use custom board timings.
-endchoice
-
-config FB_AU1100
- bool "Au1100 LCD Driver"
- depends on (FB = y) && MIPS_ALCHEMY
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This is the framebuffer driver for the AMD Au1100 SOC. It can drive
- various panels and CRTs by passing in kernel cmd line option
- au1100fb:panel=<name>.
-
-config FB_AU1200
- bool "Au1200/Au1300 LCD Driver"
- depends on (FB = y) && MIPS_ALCHEMY
- select FB_SYS_FILLRECT
- select FB_SYS_COPYAREA
- select FB_SYS_IMAGEBLIT
- select FB_SYS_FOPS
- help
- This is the framebuffer driver for the Au1200/Au1300 SOCs.
- It can drive various panels and CRTs by passing in kernel cmd line
- option au1200fb:panel=<name>.
-
-config FB_VT8500
- bool "VIA VT8500 framebuffer support"
- depends on (FB = y) && ARM && ARCH_VT8500
- select FB_SYS_FILLRECT if (!FB_WMT_GE_ROPS)
- select FB_SYS_COPYAREA if (!FB_WMT_GE_ROPS)
- select FB_SYS_IMAGEBLIT
- select FB_MODE_HELPERS
- select VIDEOMODE_HELPERS
- help
- This is the framebuffer driver for VIA VT8500 integrated LCD
- controller.
-
-config FB_WM8505
- bool "Wondermedia WM8xxx-series frame buffer support"
- depends on (FB = y) && ARM && ARCH_VT8500
- select FB_SYS_FILLRECT if (!FB_WMT_GE_ROPS)
- select FB_SYS_COPYAREA if (!FB_WMT_GE_ROPS)
- select FB_SYS_IMAGEBLIT
- select FB_MODE_HELPERS
- select VIDEOMODE_HELPERS
- help
- This is the framebuffer driver for WonderMedia WM8xxx-series
- integrated LCD controller. This driver covers the WM8505, WM8650
- and WM8850 SoCs.
-
-config FB_WMT_GE_ROPS
- bool "VT8500/WM8xxx accelerated raster ops support"
- depends on (FB = y) && (FB_VT8500 || FB_WM8505)
- default n
- help
- This adds support for accelerated raster operations on the
- VIA VT8500 and Wondermedia 85xx series SoCs.
-
-source "drivers/video/geode/Kconfig"
-
-config FB_HIT
- tristate "HD64461 Frame Buffer support"
- depends on FB && HD64461
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This is the frame buffer device driver for the Hitachi HD64461 LCD
- frame buffer card.
-
-config FB_PMAG_AA
- bool "PMAG-AA TURBOchannel framebuffer support"
- depends on (FB = y) && TC
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- Support for the PMAG-AA TURBOchannel framebuffer card (1280x1024x1)
- used mainly in the MIPS-based DECstation series.
-
-config FB_PMAG_BA
- tristate "PMAG-BA TURBOchannel framebuffer support"
- depends on FB && TC
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- Support for the PMAG-BA TURBOchannel framebuffer card (1024x864x8)
- used mainly in the MIPS-based DECstation series.
-
-config FB_PMAGB_B
- tristate "PMAGB-B TURBOchannel framebuffer support"
- depends on FB && TC
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- Support for the PMAGB-B TURBOchannel framebuffer card used mainly
- in the MIPS-based DECstation series. The card is currently only
- supported in 1280x1024x8 mode.
-
-config FB_MAXINE
- bool "Maxine (Personal DECstation) onboard framebuffer support"
- depends on (FB = y) && MACH_DECSTATION
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- Support for the onboard framebuffer (1024x768x8) in the Personal
- DECstation series (Personal DECstation 5000/20, /25, /33, /50,
- Codename "Maxine").
-
-config FB_G364
- bool "G364 frame buffer support"
- depends on (FB = y) && (MIPS_MAGNUM_4000 || OLIVETTI_M700)
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- The G364 driver is the framebuffer used in MIPS Magnum 4000 and
- Olivetti M700-10 systems.
-
-config FB_68328
- bool "Motorola 68328 native frame buffer support"
- depends on (FB = y) && (M68328 || M68EZ328 || M68VZ328)
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- Say Y here if you want to support the built-in frame buffer of
- the Motorola 68328 CPU family.
-
-config FB_PXA168
- tristate "PXA168/910 LCD framebuffer support"
- depends on FB && (CPU_PXA168 || CPU_PXA910)
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- ---help---
- Frame buffer driver for the built-in LCD controller in the Marvell
- MMP processor.
-
-config FB_PXA
- tristate "PXA LCD framebuffer support"
- depends on FB && ARCH_PXA
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- ---help---
- Frame buffer driver for the built-in LCD controller in the Intel
- PXA2x0 processor.
-
- This driver is also available as a module ( = code which can be
- inserted and removed from the running kernel whenever you want). The
- module will be called pxafb. If you want to compile it as a module,
- say M here and read <file:Documentation/kbuild/modules.txt>.
-
- If unsure, say N.
-
-config FB_PXA_OVERLAY
- bool "Support PXA27x/PXA3xx Overlay(s) as framebuffer"
- default n
- depends on FB_PXA && (PXA27x || PXA3xx)
-
-config FB_PXA_SMARTPANEL
- bool "PXA Smartpanel LCD support"
- default n
- depends on FB_PXA
-
-config FB_PXA_PARAMETERS
- bool "PXA LCD command line parameters"
- default n
- depends on FB_PXA
- ---help---
- Enable the use of kernel command line or module parameters
- to configure the physical properties of the LCD panel when
- using the PXA LCD driver.
-
- This option allows you to override the panel parameters
- supplied by the platform in order to support multiple
- different models of flatpanel. If you will only be using a
- single model of flatpanel then you can safely leave this
- option disabled.
-
- <file:Documentation/fb/pxafb.txt> describes the available parameters.
-
-config PXA3XX_GCU
- tristate "PXA3xx 2D graphics accelerator driver"
- depends on FB_PXA
- help
- Kernelspace driver for the 2D graphics controller unit (GCU)
- found on PXA3xx processors. There is a counterpart driver in the
- DirectFB suite, see http://www.directfb.org/
-
- If you compile this as a module, it will be called pxa3xx_gcu.
-
-config FB_MBX
- tristate "2700G LCD framebuffer support"
- depends on FB && ARCH_PXA
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- ---help---
- Framebuffer driver for the Intel 2700G (Marathon) Graphics
- Accelerator
-
-config FB_MBX_DEBUG
- bool "Enable debugging info via debugfs"
- depends on FB_MBX && DEBUG_FS
- default n
- ---help---
- Enable this if you want debugging information using the debug
- filesystem (debugfs)
-
- If unsure, say N.
-
-config FB_FSL_DIU
- tristate "Freescale DIU framebuffer support"
- depends on FB && FSL_SOC
- select FB_MODE_HELPERS
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select PPC_LIB_RHEAP
- ---help---
- Framebuffer driver for the Freescale SoC DIU
-
-config FB_W100
- tristate "W100 frame buffer support"
- depends on FB && ARCH_PXA
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- ---help---
- Frame buffer driver for the w100 as found on the Sharp SL-Cxx series.
- It can also drive the w3220 chip found on iPAQ hx4700.
-
- This driver is also available as a module ( = code which can be
- inserted and removed from the running kernel whenever you want). The
- module will be called w100fb. If you want to compile it as a module,
- say M here and read <file:Documentation/kbuild/modules.txt>.
-
- If unsure, say N.
-
-config FB_SH_MOBILE_LCDC
- tristate "SuperH Mobile LCDC framebuffer support"
- depends on FB && (SUPERH || ARCH_SHMOBILE) && HAVE_CLK
- select FB_SYS_FILLRECT
- select FB_SYS_COPYAREA
- select FB_SYS_IMAGEBLIT
- select FB_SYS_FOPS
- select FB_DEFERRED_IO
- select FB_BACKLIGHT
- select SH_MIPI_DSI if SH_LCD_MIPI_DSI
- ---help---
- Frame buffer driver for the on-chip SH-Mobile LCD controller.
-
-config FB_SH_MOBILE_HDMI
- tristate "SuperH Mobile HDMI controller support"
- depends on FB_SH_MOBILE_LCDC
- select FB_MODE_HELPERS
- select SOUND
- select SND
- select SND_SOC
- ---help---
- Driver for the on-chip SH-Mobile HDMI controller.
-
-config FB_TMIO
- tristate "Toshiba Mobile IO FrameBuffer support"
- depends on FB && MFD_CORE
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- ---help---
- Frame buffer driver for the Toshiba Mobile IO integrated as found
- on the Sharp SL-6000 series
-
- This driver is also available as a module ( = code which can be
- inserted and removed from the running kernel whenever you want). The
- module will be called tmiofb. If you want to compile it as a module,
- say M here and read <file:Documentation/kbuild/modules.txt>.
-
- If unsure, say N.
-
-config FB_TMIO_ACCELL
- bool "tmiofb acceleration"
- depends on FB_TMIO
- default y
-
-config FB_S3C
- tristate "Samsung S3C framebuffer support"
- depends on FB && (CPU_S3C2416 || ARCH_S3C64XX || ARCH_S5P64X0 || \
- ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS)
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- ---help---
- Frame buffer driver for the built-in FB controller in the Samsung
- SoC line from the S3C2443 onwards, including the S3C2416, S3C2450,
- and the S3C64XX series such as the S3C6400 and S3C6410.
-
- These chips all have the same basic framebuffer design with the
- actual capabilities depending on the chip. For instance the S3C6400
- and S3C6410 support 4 hardware windows whereas the S3C24XX series
- currently only have two.
-
- Currently the support is only for the S3C6400 and S3C6410 SoCs.
-
-config FB_S3C_DEBUG_REGWRITE
- bool "Debug register writes"
- depends on FB_S3C
- ---help---
- Show all register writes via pr_debug()
-
-config FB_S3C2410
- tristate "S3C2410 LCD framebuffer support"
- depends on FB && ARCH_S3C24XX
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- ---help---
- Frame buffer driver for the built-in LCD controller in the Samsung
- S3C2410 processor.
-
- This driver is also available as a module ( = code which can be
- inserted and removed from the running kernel whenever you want). The
- module will be called s3c2410fb. If you want to compile it as a module,
- say M here and read <file:Documentation/kbuild/modules.txt>.
-
- If unsure, say N.
-config FB_S3C2410_DEBUG
- bool "S3C2410 lcd debug messages"
- depends on FB_S3C2410
- help
- Turn on debugging messages. Note that you can set/unset at run time
- through sysfs
-
-config FB_NUC900
- bool "NUC900 LCD framebuffer support"
- depends on FB && ARCH_W90X900
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- ---help---
- Frame buffer driver for the built-in LCD controller in the Nuvoton
- NUC900 processor
-
-config GPM1040A0_320X240
- bool "Giantplus Technology GPM1040A0 320x240 Color TFT LCD"
- depends on FB_NUC900
-
-config FB_SM501
- tristate "Silicon Motion SM501 framebuffer support"
- depends on FB && MFD_SM501
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- ---help---
- Frame buffer driver for the CRT and LCD controllers in the Silicon
- Motion SM501.
-
- This driver is also available as a module ( = code which can be
- inserted and removed from the running kernel whenever you want). The
- module will be called sm501fb. If you want to compile it as a module,
- say M here and read <file:Documentation/kbuild/modules.txt>.
-
- If unsure, say N.
-
-config FB_SMSCUFX
- tristate "SMSC UFX6000/7000 USB Framebuffer support"
- depends on FB && USB
- select FB_MODE_HELPERS
- select FB_SYS_FILLRECT
- select FB_SYS_COPYAREA
- select FB_SYS_IMAGEBLIT
- select FB_SYS_FOPS
- select FB_DEFERRED_IO
- ---help---
- This is a kernel framebuffer driver for SMSC UFX USB devices.
- Supports fbdev clients like xf86-video-fbdev, kdrive, fbi, and
- mplayer -vo fbdev. Supports both UFX6000 (USB 2.0) and UFX7000
- (USB 3.0) devices.
- To compile as a module, choose M here: the module name is smscufx.
-
-config FB_UDL
- tristate "Displaylink USB Framebuffer support"
- depends on FB && USB
- select FB_MODE_HELPERS
- select FB_SYS_FILLRECT
- select FB_SYS_COPYAREA
- select FB_SYS_IMAGEBLIT
- select FB_SYS_FOPS
- select FB_DEFERRED_IO
- ---help---
- This is a kernel framebuffer driver for DisplayLink USB devices.
- Supports fbdev clients like xf86-video-fbdev, kdrive, fbi, and
- mplayer -vo fbdev. Supports all USB 2.0 era DisplayLink devices.
- To compile as a module, choose M here: the module name is udlfb.
-
-config FB_IBM_GXT4500
- tristate "Framebuffer support for IBM GXT4000P/4500P/6000P/6500P adaptors"
- depends on FB && PPC
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- ---help---
- Say Y here to enable support for the IBM GXT4000P/6000P and
- GXT4500P/6500P display adaptor based on Raster Engine RC1000,
- found on some IBM System P (pSeries) machines. This driver
- doesn't use Geometry Engine GT1000.
-
-config FB_PS3
- tristate "PS3 GPU framebuffer driver"
- depends on FB && PS3_PS3AV
- select FB_SYS_FILLRECT
- select FB_SYS_COPYAREA
- select FB_SYS_IMAGEBLIT
- select FB_SYS_FOPS
- select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE
- ---help---
- Include support for the virtual frame buffer in the PS3 platform.
-
-config FB_PS3_DEFAULT_SIZE_M
- int "PS3 default frame buffer size (in MiB)"
- depends on FB_PS3
- default 9
- ---help---
- This is the default size (in MiB) of the virtual frame buffer in
- the PS3.
- The default value can be overridden on the kernel command line
- using the "ps3fb" option (e.g. "ps3fb=9M");
-
-config FB_XILINX
- tristate "Xilinx frame buffer support"
- depends on FB && (XILINX_VIRTEX || MICROBLAZE || ARCH_ZYNQ)
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- ---help---
- Include support for the Xilinx ML300/ML403 reference design
- framebuffer. ML300 carries a 640*480 LCD display on the board,
- ML403 uses a standard DB15 VGA connector.
-
-config FB_GOLDFISH
- tristate "Goldfish Framebuffer"
- depends on FB && HAS_DMA
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- ---help---
- Framebuffer driver for Goldfish Virtual Platform
-
-config FB_COBALT
- tristate "Cobalt server LCD frame buffer support"
- depends on FB && (MIPS_COBALT || MIPS_SEAD3)
-
-config FB_SH7760
- bool "SH7760/SH7763/SH7720/SH7721 LCDC support"
- depends on FB && (CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7763 \
- || CPU_SUBTYPE_SH7720 || CPU_SUBTYPE_SH7721)
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- ---help---
- Support for the SH7760/SH7763/SH7720/SH7721 integrated
- (D)STN/TFT LCD Controller.
- Supports display resolutions up to 1024x1024 pixel, grayscale and
- color operation, with depths ranging from 1 bpp to 8 bpp monochrome
- and 8, 15 or 16 bpp color; 90 degrees clockwise display rotation for
- panels <= 320 pixel horizontal resolution.
-
-config FB_DA8XX
- tristate "DA8xx/OMAP-L1xx/AM335x Framebuffer support"
- depends on FB && (ARCH_DAVINCI_DA8XX || SOC_AM33XX)
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select FB_CFB_REV_PIXELS_IN_BYTE
- select FB_MODE_HELPERS
- select VIDEOMODE_HELPERS
- ---help---
- This is the frame buffer device driver for the TI LCD controller
- found on DA8xx/OMAP-L1xx/AM335x SoCs.
- If unsure, say N.
-
-config FB_VIRTUAL
- tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
- depends on FB
- select FB_SYS_FILLRECT
- select FB_SYS_COPYAREA
- select FB_SYS_IMAGEBLIT
- select FB_SYS_FOPS
- ---help---
- This is a `virtual' frame buffer device. It operates on a chunk of
- unswappable kernel memory instead of on the memory of a graphics
- board. This means you cannot see any output sent to this frame
- buffer device, while it does consume precious memory. The main use
- of this frame buffer device is testing and debugging the frame
- buffer subsystem. Do NOT enable it for normal systems! To protect
- the innocent, it has to be enabled explicitly at boot time using the
- kernel option `video=vfb:'.
-
- To compile this driver as a module, choose M here: the
- module will be called vfb. In order to load it, you must use
- the vfb_enable=1 option.
-
- If unsure, say N.
-
-config XEN_FBDEV_FRONTEND
- tristate "Xen virtual frame buffer support"
- depends on FB && XEN
- select FB_SYS_FILLRECT
- select FB_SYS_COPYAREA
- select FB_SYS_IMAGEBLIT
- select FB_SYS_FOPS
- select FB_DEFERRED_IO
- select INPUT_XEN_KBDDEV_FRONTEND if INPUT_MISC
- select XEN_XENBUS_FRONTEND
- default y
- help
- This driver implements the front-end of the Xen virtual
- frame buffer driver. It communicates with a back-end
- in another domain.
-
-config FB_METRONOME
- tristate "E-Ink Metronome/8track controller support"
- depends on FB
- select FB_SYS_FILLRECT
- select FB_SYS_COPYAREA
- select FB_SYS_IMAGEBLIT
- select FB_SYS_FOPS
- select FB_DEFERRED_IO
- help
- This driver implements support for the E-Ink Metronome
- controller. The pre-release name for this device was 8track
- and could also have been called by some vendors as PVI-nnnn.
-
-config FB_MB862XX
- tristate "Fujitsu MB862xx GDC support"
- depends on FB
- depends on PCI || (OF && PPC)
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- ---help---
- Frame buffer driver for Fujitsu Carmine/Coral-P(A)/Lime controllers.
-
-choice
- prompt "GDC variant"
- depends on FB_MB862XX
-
-config FB_MB862XX_PCI_GDC
- bool "Carmine/Coral-P(A) GDC"
- depends on PCI
- ---help---
- This enables framebuffer support for Fujitsu Carmine/Coral-P(A)
- PCI graphics controller devices.
-
-config FB_MB862XX_LIME
- bool "Lime GDC"
- depends on OF && PPC
- select FB_FOREIGN_ENDIAN
- select FB_LITTLE_ENDIAN
- ---help---
- Framebuffer support for Fujitsu Lime GDC on host CPU bus.
-
-endchoice
-
-config FB_MB862XX_I2C
- bool "Support I2C bus on MB862XX GDC"
- depends on FB_MB862XX && I2C
- default y
- help
- Selecting this option adds Coral-P(A)/Lime GDC I2C bus adapter
- driver to support accessing I2C devices on controller's I2C bus.
- These are usually some video decoder chips.
-
-config FB_EP93XX
- tristate "EP93XX frame buffer support"
- depends on FB && ARCH_EP93XX
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- ---help---
- Framebuffer driver for the Cirrus Logic EP93XX series of processors.
- This driver is also available as a module. The module will be called
- ep93xx-fb.
-
-config FB_PRE_INIT_FB
- bool "Don't reinitialize, use bootloader's GDC/Display configuration"
- depends on FB && FB_MB862XX_LIME
- ---help---
- Select this option if display contents should be inherited as set by
- the bootloader.
-
-config FB_MSM
- tristate "MSM Framebuffer support"
- depends on FB && ARCH_MSM
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
-
-config FB_MX3
- tristate "MX3 Framebuffer support"
- depends on FB && MX3_IPU
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- default y
- help
- This is a framebuffer device for the i.MX31 LCD Controller. So
- far only synchronous displays are supported. If you plan to use
- an LCD display with your i.MX31 system, say Y here.
-
-config FB_BROADSHEET
- tristate "E-Ink Broadsheet/Epson S1D13521 controller support"
- depends on FB
- select FB_SYS_FILLRECT
- select FB_SYS_COPYAREA
- select FB_SYS_IMAGEBLIT
- select FB_SYS_FOPS
- select FB_DEFERRED_IO
- help
- This driver implements support for the E-Ink Broadsheet
- controller. The release name for this device was Epson S1D13521
- and could also have been called by other names when coupled with
- a bridge adapter.
-
-config FB_AUO_K190X
- tristate "AUO-K190X EPD controller support"
- depends on FB
- select FB_SYS_FILLRECT
- select FB_SYS_COPYAREA
- select FB_SYS_IMAGEBLIT
- select FB_SYS_FOPS
- select FB_DEFERRED_IO
- help
- Provides support for epaper controllers from the K190X series
- of AUO. These controllers can be used to drive epaper displays
- from Sipix.
-
- This option enables the common support, shared by the individual
- controller drivers. You will also have to enable the driver
- for the controller type used in your device.
-
-config FB_AUO_K1900
- tristate "AUO-K1900 EPD controller support"
- depends on FB && FB_AUO_K190X
- help
- This driver implements support for the AUO K1900 epd-controller.
- This controller can drive Sipix epaper displays but can only do
- serial updates, reducing the number of possible frames per second.
-
-config FB_AUO_K1901
- tristate "AUO-K1901 EPD controller support"
- depends on FB && FB_AUO_K190X
- help
- This driver implements support for the AUO K1901 epd-controller.
- This controller can drive Sipix epaper displays and supports
- concurrent updates, making higher frames per second possible.
-
-config FB_JZ4740
- tristate "JZ4740 LCD framebuffer support"
- depends on FB && MACH_JZ4740
- select FB_SYS_FILLRECT
- select FB_SYS_COPYAREA
- select FB_SYS_IMAGEBLIT
- help
- Framebuffer support for the JZ4740 SoC.
-
-config FB_MXS
- tristate "MXS LCD framebuffer support"
- depends on FB && ARCH_MXS
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select FB_MODE_HELPERS
- select VIDEOMODE_HELPERS
- help
- Framebuffer support for the MXS SoC.
-
-config FB_PUV3_UNIGFX
- tristate "PKUnity v3 Unigfx framebuffer support"
- depends on FB && UNICORE32 && ARCH_PUV3
- select FB_SYS_FILLRECT
- select FB_SYS_COPYAREA
- select FB_SYS_IMAGEBLIT
- select FB_SYS_FOPS
- help
- Choose this option if you want to use the Unigfx device as a
- framebuffer device. Without the support of PCI & AGP.
-
-config FB_HYPERV
- tristate "Microsoft Hyper-V Synthetic Video support"
- depends on FB && HYPERV
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- This framebuffer driver supports Microsoft Hyper-V Synthetic Video.
-
-config FB_SIMPLE
- bool "Simple framebuffer support"
- depends on (FB = y)
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- Say Y if you want support for a simple frame-buffer.
-
- This driver assumes that the display hardware has been initialized
- before the kernel boots, and the kernel will simply render to the
- pre-allocated frame buffer surface.
-
- Configuration re: surface address, size, and format must be provided
- through device tree, or plain old platform data.
-
-source "drivers/video/omap/Kconfig"
-source "drivers/video/omap2/Kconfig"
-source "drivers/video/exynos/Kconfig"
-source "drivers/video/mmp/Kconfig"
-source "drivers/video/backlight/Kconfig"
-
if VT
source "drivers/video/console/Kconfig"
endif
if FB || SGI_NEWPORT_CONSOLE
source "drivers/video/logo/Kconfig"
-endif
-config FB_SH_MOBILE_MERAM
- tristate "SuperH Mobile MERAM read ahead support"
- depends on (SUPERH || ARCH_SHMOBILE)
- select GENERIC_ALLOCATOR
- ---help---
- Enable MERAM support for the SuperH controller.
-
- This will allow for caching of the framebuffer to provide more
- reliable access under heavy main memory bus traffic situations.
- Up to 4 memory channels can be configured, allowing 4 RGB or
- 2 YCbCr framebuffers to be configured.
+endif
-config FB_SSD1307
- tristate "Solomon SSD1307 framebuffer support"
- depends on FB && I2C
- depends on OF
- depends on GPIOLIB
- select FB_SYS_FOPS
- select FB_SYS_FILLRECT
- select FB_SYS_COPYAREA
- select FB_SYS_IMAGEBLIT
- select FB_DEFERRED_IO
- select PWM
- help
- This driver implements support for the Solomon SSD1307
- OLED controller over I2C.
endmenu
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 1be26fe10592..9ad3c17d6456 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -1,175 +1,11 @@
-# Makefile for the Linux video drivers.
-# 5 Aug 1999, James Simmons, <mailto:jsimmons@users.sf.net>
-# Rewritten to use lists instead of if-statements.
-
-# Each configuration option enables a list of files.
-
obj-$(CONFIG_VGASTATE) += vgastate.o
obj-$(CONFIG_HDMI) += hdmi.o
-obj-y += fb_notify.o
-obj-$(CONFIG_FB) += fb.o
-fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \
- modedb.o fbcvt.o
-fb-objs := $(fb-y)
obj-$(CONFIG_VT) += console/
obj-$(CONFIG_LOGO) += logo/
obj-y += backlight/
-obj-$(CONFIG_EXYNOS_VIDEO) += exynos/
-
-obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o
-obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o
-obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o
-obj-$(CONFIG_FB_SYS_FILLRECT) += sysfillrect.o
-obj-$(CONFIG_FB_SYS_COPYAREA) += syscopyarea.o
-obj-$(CONFIG_FB_SYS_IMAGEBLIT) += sysimgblt.o
-obj-$(CONFIG_FB_SYS_FOPS) += fb_sys_fops.o
-obj-$(CONFIG_FB_SVGALIB) += svgalib.o
-obj-$(CONFIG_FB_MACMODES) += macmodes.o
-obj-$(CONFIG_FB_DDC) += fb_ddc.o
-obj-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o
-obj-$(CONFIG_FB_WMT_GE_ROPS) += wmt_ge_rops.o
-
-# Hardware specific drivers go first
-obj-$(CONFIG_FB_AMIGA) += amifb.o c2p_planar.o
-obj-$(CONFIG_FB_ARC) += arcfb.o
-obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o
-obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o
-obj-$(CONFIG_FB_GRVGA) += grvga.o
-obj-$(CONFIG_FB_PM2) += pm2fb.o
-obj-$(CONFIG_FB_PM3) += pm3fb.o
-
-obj-$(CONFIG_FB_I740) += i740fb.o
-obj-$(CONFIG_FB_MATROX) += matrox/
-obj-$(CONFIG_FB_RIVA) += riva/
-obj-$(CONFIG_FB_NVIDIA) += nvidia/
-obj-$(CONFIG_FB_ATY) += aty/ macmodes.o
-obj-$(CONFIG_FB_ATY128) += aty/ macmodes.o
-obj-$(CONFIG_FB_RADEON) += aty/
-obj-$(CONFIG_FB_SIS) += sis/
-obj-$(CONFIG_FB_VIA) += via/
-obj-$(CONFIG_FB_KYRO) += kyro/
-obj-$(CONFIG_FB_SAVAGE) += savage/
-obj-$(CONFIG_FB_GEODE) += geode/
-obj-$(CONFIG_FB_MBX) += mbx/
-obj-$(CONFIG_FB_NEOMAGIC) += neofb.o
-obj-$(CONFIG_FB_3DFX) += tdfxfb.o
-obj-$(CONFIG_FB_CONTROL) += controlfb.o
-obj-$(CONFIG_FB_PLATINUM) += platinumfb.o
-obj-$(CONFIG_FB_VALKYRIE) += valkyriefb.o
-obj-$(CONFIG_FB_CT65550) += chipsfb.o
-obj-$(CONFIG_FB_IMSTT) += imsttfb.o
-obj-$(CONFIG_FB_FM2) += fm2fb.o
-obj-$(CONFIG_FB_VT8623) += vt8623fb.o
-obj-$(CONFIG_FB_TRIDENT) += tridentfb.o
-obj-$(CONFIG_FB_LE80578) += vermilion/
-obj-$(CONFIG_FB_S3) += s3fb.o
-obj-$(CONFIG_FB_ARK) += arkfb.o
-obj-$(CONFIG_FB_STI) += stifb.o
-obj-$(CONFIG_FB_FFB) += ffb.o sbuslib.o
-obj-$(CONFIG_FB_CG6) += cg6.o sbuslib.o
-obj-$(CONFIG_FB_CG3) += cg3.o sbuslib.o
-obj-$(CONFIG_FB_BW2) += bw2.o sbuslib.o
-obj-$(CONFIG_FB_CG14) += cg14.o sbuslib.o
-obj-$(CONFIG_FB_P9100) += p9100.o sbuslib.o
-obj-$(CONFIG_FB_TCX) += tcx.o sbuslib.o
-obj-$(CONFIG_FB_LEO) += leo.o sbuslib.o
-obj-$(CONFIG_FB_ACORN) += acornfb.o
-obj-$(CONFIG_FB_ATARI) += atafb.o c2p_iplan2.o atafb_mfb.o \
- atafb_iplan2p2.o atafb_iplan2p4.o atafb_iplan2p8.o
-obj-$(CONFIG_FB_MAC) += macfb.o
-obj-$(CONFIG_FB_HECUBA) += hecubafb.o
-obj-$(CONFIG_FB_N411) += n411.o
-obj-$(CONFIG_FB_HGA) += hgafb.o
-obj-$(CONFIG_FB_XVR500) += sunxvr500.o
-obj-$(CONFIG_FB_XVR2500) += sunxvr2500.o
-obj-$(CONFIG_FB_XVR1000) += sunxvr1000.o
-obj-$(CONFIG_FB_IGA) += igafb.o
-obj-$(CONFIG_FB_APOLLO) += dnfb.o
-obj-$(CONFIG_FB_Q40) += q40fb.o
-obj-$(CONFIG_FB_TGA) += tgafb.o
-obj-$(CONFIG_FB_HP300) += hpfb.o
-obj-$(CONFIG_FB_G364) += g364fb.o
-obj-$(CONFIG_FB_EP93XX) += ep93xx-fb.o
-obj-$(CONFIG_FB_SA1100) += sa1100fb.o
-obj-$(CONFIG_FB_HIT) += hitfb.o
-obj-$(CONFIG_FB_ATMEL) += atmel_lcdfb.o
-obj-$(CONFIG_FB_PVR2) += pvr2fb.o
-obj-$(CONFIG_FB_VOODOO1) += sstfb.o
-obj-$(CONFIG_FB_ARMCLCD) += amba-clcd.o
-obj-$(CONFIG_FB_GOLDFISH) += goldfishfb.o
-obj-$(CONFIG_FB_68328) += 68328fb.o
-obj-$(CONFIG_FB_GBE) += gbefb.o
-obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o
-obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o
-obj-$(CONFIG_FB_PXA) += pxafb.o
-obj-$(CONFIG_FB_PXA168) += pxa168fb.o
-obj-$(CONFIG_PXA3XX_GCU) += pxa3xx-gcu.o
-obj-$(CONFIG_MMP_DISP) += mmp/
-obj-$(CONFIG_FB_W100) += w100fb.o
-obj-$(CONFIG_FB_TMIO) += tmiofb.o
-obj-$(CONFIG_FB_AU1100) += au1100fb.o
-obj-$(CONFIG_FB_AU1200) += au1200fb.o
-obj-$(CONFIG_FB_VT8500) += vt8500lcdfb.o
-obj-$(CONFIG_FB_WM8505) += wm8505fb.o
-obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.o
-obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o
-obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o
-obj-$(CONFIG_FB_MAXINE) += maxinefb.o
-obj-$(CONFIG_FB_METRONOME) += metronomefb.o
-obj-$(CONFIG_FB_BROADSHEET) += broadsheetfb.o
-obj-$(CONFIG_FB_AUO_K190X) += auo_k190x.o
-obj-$(CONFIG_FB_AUO_K1900) += auo_k1900fb.o
-obj-$(CONFIG_FB_AUO_K1901) += auo_k1901fb.o
-obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o
-obj-$(CONFIG_FB_SH7760) += sh7760fb.o
-obj-$(CONFIG_FB_IMX) += imxfb.o
-obj-$(CONFIG_FB_S3C) += s3c-fb.o
-obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o
-obj-$(CONFIG_FB_FSL_DIU) += fsl-diu-fb.o
-obj-$(CONFIG_FB_COBALT) += cobalt_lcdfb.o
-obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o
-obj-$(CONFIG_FB_PS3) += ps3fb.o
-obj-$(CONFIG_FB_SM501) += sm501fb.o
-obj-$(CONFIG_FB_UDL) += udlfb.o
-obj-$(CONFIG_FB_SMSCUFX) += smscufx.o
-obj-$(CONFIG_FB_XILINX) += xilinxfb.o
-obj-$(CONFIG_SH_MIPI_DSI) += sh_mipi_dsi.o
-obj-$(CONFIG_FB_SH_MOBILE_HDMI) += sh_mobile_hdmi.o
-obj-$(CONFIG_FB_SH_MOBILE_MERAM) += sh_mobile_meram.o
-obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o
-obj-$(CONFIG_FB_OMAP) += omap/
-obj-y += omap2/
-obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o
-obj-$(CONFIG_FB_CARMINE) += carminefb.o
-obj-$(CONFIG_FB_MB862XX) += mb862xx/
-obj-$(CONFIG_FB_MSM) += msm/
-obj-$(CONFIG_FB_NUC900) += nuc900fb.o
-obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o
-obj-$(CONFIG_FB_PUV3_UNIGFX) += fb-puv3.o
-obj-$(CONFIG_FB_HYPERV) += hyperv_fb.o
-obj-$(CONFIG_FB_OPENCORES) += ocfb.o
-
-# Platform or fallback drivers go here
-obj-$(CONFIG_FB_UVESA) += uvesafb.o
-obj-$(CONFIG_FB_VESA) += vesafb.o
-obj-$(CONFIG_FB_EFI) += efifb.o
-obj-$(CONFIG_FB_VGA16) += vga16fb.o
-obj-$(CONFIG_FB_OF) += offb.o
-obj-$(CONFIG_FB_BF537_LQ035) += bf537-lq035.o
-obj-$(CONFIG_FB_BF54X_LQ043) += bf54x-lq043fb.o
-obj-$(CONFIG_FB_BFIN_LQ035Q1) += bfin-lq035q1-fb.o
-obj-$(CONFIG_FB_BFIN_T350MCQB) += bfin-t350mcqb-fb.o
-obj-$(CONFIG_FB_BFIN_7393) += bfin_adv7393fb.o
-obj-$(CONFIG_FB_MX3) += mx3fb.o
-obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o
-obj-$(CONFIG_FB_MXS) += mxsfb.o
-obj-$(CONFIG_FB_SSD1307) += ssd1307fb.o
-obj-$(CONFIG_FB_SIMPLE) += simplefb.o
-
-# the test framebuffer is last
-obj-$(CONFIG_FB_VIRTUAL) += vfb.o
+obj-y += fbdev/
obj-$(CONFIG_VIDEOMODE_HELPERS) += display_timing.o videomode.o
ifeq ($(CONFIG_OF),y)
diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c
index 5f65ca3d8564..026fd1215933 100644
--- a/drivers/video/console/sticon.c
+++ b/drivers/video/console/sticon.c
@@ -46,7 +46,7 @@
#include <asm/io.h>
-#include "../sticore.h"
+#include "../fbdev/sticore.h"
/* switching to graphics mode */
#define BLANK 0
diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c
index cecd3de01c24..7da1ad03acb5 100644
--- a/drivers/video/console/sticore.c
+++ b/drivers/video/console/sticore.c
@@ -28,7 +28,7 @@
#include <asm/cacheflush.h>
#include <asm/grfioctl.h>
-#include "../sticore.h"
+#include "../fbdev/sticore.h"
#define STI_DRIVERVERSION "Version 0.9b"
diff --git a/drivers/video/68328fb.c b/drivers/video/fbdev/68328fb.c
index 552258c8f99d..552258c8f99d 100644
--- a/drivers/video/68328fb.c
+++ b/drivers/video/fbdev/68328fb.c
diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
new file mode 100644
index 000000000000..e1f47272fdea
--- /dev/null
+++ b/drivers/video/fbdev/Kconfig
@@ -0,0 +1,2474 @@
+#
+# fbdev configuration
+#
+
+menuconfig FB
+ tristate "Support for frame buffer devices"
+ ---help---
+ The frame buffer device provides an abstraction for the graphics
+ hardware. It represents the frame buffer of some video hardware and
+ allows application software to access the graphics hardware through
+ a well-defined interface, so the software doesn't need to know
+ anything about the low-level (hardware register) stuff.
+
+ Frame buffer devices work identically across the different
+ architectures supported by Linux and make the implementation of
+ application programs easier and more portable; at this point, an X
+ server exists which uses the frame buffer device exclusively.
+ On several non-X86 architectures, the frame buffer device is the
+ only way to use the graphics hardware.
+
+ The device is accessed through special device nodes, usually located
+ in the /dev directory, i.e. /dev/fb*.
+
+ You need an utility program called fbset to make full use of frame
+ buffer devices. Please read <file:Documentation/fb/framebuffer.txt>
+ and the Framebuffer-HOWTO at
+ <http://www.munted.org.uk/programming/Framebuffer-HOWTO-1.3.html> for more
+ information.
+
+ Say Y here and to the driver for your graphics board below if you
+ are compiling a kernel for a non-x86 architecture.
+
+ If you are compiling for the x86 architecture, you can say Y if you
+ want to play with it, but it is not essential. Please note that
+ running graphical applications that directly touch the hardware
+ (e.g. an accelerated X server) and that are not frame buffer
+ device-aware may cause unexpected results. If unsure, say N.
+
+config FIRMWARE_EDID
+ bool "Enable firmware EDID"
+ depends on FB
+ default n
+ ---help---
+ This enables access to the EDID transferred from the firmware.
+ On the i386, this is from the Video BIOS. Enable this if DDC/I2C
+ transfers do not work for your driver and if you are using
+ nvidiafb, i810fb or savagefb.
+
+ In general, choosing Y for this option is safe. If you
+ experience extremely long delays while booting before you get
+ something on your display, try setting this to N. Matrox cards in
+ combination with certain motherboards and monitors are known to
+ suffer from this problem.
+
+config FB_DDC
+ tristate
+ depends on FB
+ select I2C_ALGOBIT
+ select I2C
+ default n
+
+config FB_BOOT_VESA_SUPPORT
+ bool
+ depends on FB
+ default n
+ ---help---
+ If true, at least one selected framebuffer driver can take advantage
+ of VESA video modes set at an early boot stage via the vga= parameter.
+
+config FB_CFB_FILLRECT
+ tristate
+ depends on FB
+ default n
+ ---help---
+ Include the cfb_fillrect function for generic software rectangle
+ filling. This is used by drivers that don't provide their own
+ (accelerated) version.
+
+config FB_CFB_COPYAREA
+ tristate
+ depends on FB
+ default n
+ ---help---
+ Include the cfb_copyarea function for generic software area copying.
+ This is used by drivers that don't provide their own (accelerated)
+ version.
+
+config FB_CFB_IMAGEBLIT
+ tristate
+ depends on FB
+ default n
+ ---help---
+ Include the cfb_imageblit function for generic software image
+ blitting. This is used by drivers that don't provide their own
+ (accelerated) version.
+
+config FB_CFB_REV_PIXELS_IN_BYTE
+ bool
+ depends on FB
+ default n
+ ---help---
+ Allow generic frame-buffer functions to work on displays with 1, 2
+ and 4 bits per pixel depths which has opposite order of pixels in
+ byte order to bytes in long order.
+
+config FB_SYS_FILLRECT
+ tristate
+ depends on FB
+ default n
+ ---help---
+ Include the sys_fillrect function for generic software rectangle
+ filling. This is used by drivers that don't provide their own
+ (accelerated) version and the framebuffer is in system RAM.
+
+config FB_SYS_COPYAREA
+ tristate
+ depends on FB
+ default n
+ ---help---
+ Include the sys_copyarea function for generic software area copying.
+ This is used by drivers that don't provide their own (accelerated)
+ version and the framebuffer is in system RAM.
+
+config FB_SYS_IMAGEBLIT
+ tristate
+ depends on FB
+ default n
+ ---help---
+ Include the sys_imageblit function for generic software image
+ blitting. This is used by drivers that don't provide their own
+ (accelerated) version and the framebuffer is in system RAM.
+
+menuconfig FB_FOREIGN_ENDIAN
+ bool "Framebuffer foreign endianness support"
+ depends on FB
+ ---help---
+ This menu will let you enable support for the framebuffers with
+ non-native endianness (e.g. Little-Endian framebuffer on a
+ Big-Endian machine). Most probably you don't have such hardware,
+ so it's safe to say "n" here.
+
+choice
+ prompt "Choice endianness support"
+ depends on FB_FOREIGN_ENDIAN
+
+config FB_BOTH_ENDIAN
+ bool "Support for Big- and Little-Endian framebuffers"
+
+config FB_BIG_ENDIAN
+ bool "Support for Big-Endian framebuffers only"
+
+config FB_LITTLE_ENDIAN
+ bool "Support for Little-Endian framebuffers only"
+
+endchoice
+
+config FB_SYS_FOPS
+ tristate
+ depends on FB
+ default n
+
+config FB_DEFERRED_IO
+ bool
+ depends on FB
+
+config FB_HECUBA
+ tristate
+ depends on FB
+ depends on FB_DEFERRED_IO
+
+config FB_SVGALIB
+ tristate
+ depends on FB
+ default n
+ ---help---
+ Common utility functions useful to fbdev drivers of VGA-based
+ cards.
+
+config FB_MACMODES
+ tristate
+ depends on FB
+ default n
+
+config FB_BACKLIGHT
+ bool
+ depends on FB
+ select BACKLIGHT_LCD_SUPPORT
+ select BACKLIGHT_CLASS_DEVICE
+ default n
+
+config FB_MODE_HELPERS
+ bool "Enable Video Mode Handling Helpers"
+ depends on FB
+ default n
+ ---help---
+ This enables functions for handling video modes using the
+ Generalized Timing Formula and the EDID parser. A few drivers rely
+ on this feature such as the radeonfb, rivafb, and the i810fb. If
+ your driver does not take advantage of this feature, choosing Y will
+ just increase the kernel size by about 5K.
+
+config FB_TILEBLITTING
+ bool "Enable Tile Blitting Support"
+ depends on FB
+ default n
+ ---help---
+ This enables tile blitting. Tile blitting is a drawing technique
+ where the screen is divided into rectangular sections (tiles), whereas
+ the standard blitting divides the screen into pixels. Because the
+ default drawing element is a tile, drawing functions will be passed
+ parameters in terms of number of tiles instead of number of pixels.
+ For example, to draw a single character, instead of using bitmaps,
+ an index to an array of bitmaps will be used. To clear or move a
+ rectangular section of a screen, the rectangle will be described in
+ terms of number of tiles in the x- and y-axis.
+
+ This is particularly important to one driver, matroxfb. If
+ unsure, say N.
+
+comment "Frame buffer hardware drivers"
+ depends on FB
+
+config FB_GRVGA
+ tristate "Aeroflex Gaisler framebuffer support"
+ depends on FB && SPARC
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ ---help---
+ This enables support for the SVGACTRL framebuffer in the GRLIB IP library from Aeroflex Gaisler.
+
+config FB_CIRRUS
+ tristate "Cirrus Logic support"
+ depends on FB && (ZORRO || PCI)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ ---help---
+ This enables support for Cirrus Logic GD542x/543x based boards on
+ Amiga: SD64, Piccolo, Picasso II/II+, Picasso IV, or EGS Spectrum.
+
+ If you have a PCI-based system, this enables support for these
+ chips: GD-543x, GD-544x, GD-5480.
+
+ Please read the file <file:Documentation/fb/cirrusfb.txt>.
+
+ Say N unless you have such a graphics board or plan to get one
+ before you next recompile the kernel.
+
+config FB_PM2
+ tristate "Permedia2 support"
+ depends on FB && ((AMIGA && BROKEN) || PCI)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the frame buffer device driver for cards based on
+ the 3D Labs Permedia, Permedia 2 and Permedia 2V chips.
+ The driver was tested on the following cards:
+ Diamond FireGL 1000 PRO AGP
+ ELSA Gloria Synergy PCI
+ Appian Jeronimo PRO (both heads) PCI
+ 3DLabs Oxygen ACX aka EONtronics Picasso P2 PCI
+ Techsource Raptor GFX-8P (aka Sun PGX-32) on SPARC
+ ASK Graphic Blaster Exxtreme AGP
+
+ To compile this driver as a module, choose M here: the
+ module will be called pm2fb.
+
+config FB_PM2_FIFO_DISCONNECT
+ bool "enable FIFO disconnect feature"
+ depends on FB_PM2 && PCI
+ help
+ Support the Permedia2 FIFO disconnect feature.
+
+config FB_ARMCLCD
+ tristate "ARM PrimeCell PL110 support"
+ depends on ARM || ARM64 || COMPILE_TEST
+ depends on FB && ARM_AMBA
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This framebuffer device driver is for the ARM PrimeCell PL110
+ Colour LCD controller. ARM PrimeCells provide the building
+ blocks for System on a Chip devices.
+
+ If you want to compile this as a module (=code which can be
+ inserted into and removed from the running kernel), say M
+ here and read <file:Documentation/kbuild/modules.txt>. The module
+ will be called amba-clcd.
+
+config FB_ACORN
+ bool "Acorn VIDC support"
+ depends on (FB = y) && ARM && ARCH_ACORN
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the frame buffer device driver for the Acorn VIDC graphics
+ hardware found in Acorn RISC PCs and other ARM-based machines. If
+ unsure, say N.
+
+config FB_CLPS711X
+ bool "CLPS711X LCD support"
+ depends on (FB = y) && ARM && ARCH_CLPS711X
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ Say Y to enable the Framebuffer driver for the CLPS7111 and
+ EP7212 processors.
+
+config FB_SA1100
+ bool "SA-1100 LCD support"
+ depends on (FB = y) && ARM && ARCH_SA1100
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is a framebuffer device for the SA-1100 LCD Controller.
+ See <http://www.linux-fbdev.org/> for information on framebuffer
+ devices.
+
+ If you plan to use the LCD display with your SA-1100 system, say
+ Y here.
+
+config FB_IMX
+ tristate "Freescale i.MX1/21/25/27 LCD support"
+ depends on FB && ARCH_MXC
+ select BACKLIGHT_LCD_SUPPORT
+ select LCD_CLASS_DEVICE
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_MODE_HELPERS
+ select VIDEOMODE_HELPERS
+
+config FB_CYBER2000
+ tristate "CyberPro 2000/2010/5000 support"
+ depends on FB && PCI && (BROKEN || !SPARC64)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This enables support for the Integraphics CyberPro 20x0 and 5000
+ VGA chips used in the Rebel.com Netwinder and other machines.
+ Say Y if you have a NetWinder or a graphics card containing this
+ device, otherwise say N.
+
+config FB_CYBER2000_DDC
+ bool "DDC for CyberPro support"
+ depends on FB_CYBER2000
+ select FB_DDC
+ default y
+ help
+ Say Y here if you want DDC support for your CyberPro graphics
+ card. This is only I2C bus support, driver does not use EDID.
+
+config FB_CYBER2000_I2C
+ bool "CyberPro 2000/2010/5000 I2C support"
+ depends on FB_CYBER2000 && I2C && ARCH_NETWINDER
+ select I2C_ALGOBIT
+ help
+ Enable support for the I2C video decoder interface on the
+ Integraphics CyberPro 20x0 and 5000 VGA chips. This is used
+ on the Netwinder machines for the SAA7111 video capture.
+
+config FB_APOLLO
+ bool
+ depends on (FB = y) && APOLLO
+ default y
+ select FB_CFB_FILLRECT
+ select FB_CFB_IMAGEBLIT
+
+config FB_Q40
+ bool
+ depends on (FB = y) && Q40
+ default y
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+
+config FB_AMIGA
+ tristate "Amiga native chipset support"
+ depends on FB && AMIGA
+ help
+ This is the frame buffer device driver for the builtin graphics
+ chipset found in Amigas.
+
+ To compile this driver as a module, choose M here: the
+ module will be called amifb.
+
+config FB_AMIGA_OCS
+ bool "Amiga OCS chipset support"
+ depends on FB_AMIGA
+ help
+ This enables support for the original Agnus and Denise video chips,
+ found in the Amiga 1000 and most A500's and A2000's. If you intend
+ to run Linux on any of these systems, say Y; otherwise say N.
+
+config FB_AMIGA_ECS
+ bool "Amiga ECS chipset support"
+ depends on FB_AMIGA
+ help
+ This enables support for the Enhanced Chip Set, found in later
+ A500's, later A2000's, the A600, the A3000, the A3000T and CDTV. If
+ you intend to run Linux on any of these systems, say Y; otherwise
+ say N.
+
+config FB_AMIGA_AGA
+ bool "Amiga AGA chipset support"
+ depends on FB_AMIGA
+ help
+ This enables support for the Advanced Graphics Architecture (also
+ known as the AGA or AA) Chip Set, found in the A1200, A4000, A4000T
+ and CD32. If you intend to run Linux on any of these systems, say Y;
+ otherwise say N.
+
+config FB_FM2
+ bool "Amiga FrameMaster II/Rainbow II support"
+ depends on (FB = y) && ZORRO
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the frame buffer device driver for the Amiga FrameMaster
+ card from BSC (exhibited 1992 but not shipped as a CBM product).
+
+config FB_ARC
+ tristate "Arc Monochrome LCD board support"
+ depends on FB && X86
+ select FB_SYS_FILLRECT
+ select FB_SYS_COPYAREA
+ select FB_SYS_IMAGEBLIT
+ select FB_SYS_FOPS
+ help
+ This enables support for the Arc Monochrome LCD board. The board
+ is based on the KS-108 lcd controller and is typically a matrix
+ of 2*n chips. This driver was tested with a 128x64 panel. This
+ driver supports it for use with x86 SBCs through a 16 bit GPIO
+ interface (8 bit data, 8 bit control). If you anticipate using
+ this driver, say Y or M; otherwise say N. You must specify the
+ GPIO IO address to be used for setting control and data.
+
+config FB_ATARI
+ bool "Atari native chipset support"
+ depends on (FB = y) && ATARI
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the frame buffer device driver for the builtin graphics
+ chipset found in Ataris.
+
+config FB_OF
+ bool "Open Firmware frame buffer device support"
+ depends on (FB = y) && (PPC64 || PPC_OF) && (!PPC_PSERIES || PCI)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_MACMODES
+ help
+ Say Y if you want support with Open Firmware for your graphics
+ board.
+
+config FB_CONTROL
+ bool "Apple \"control\" display support"
+ depends on (FB = y) && PPC_PMAC && PPC32
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_MACMODES
+ help
+ This driver supports a frame buffer for the graphics adapter in the
+ Power Macintosh 7300 and others.
+
+config FB_PLATINUM
+ bool "Apple \"platinum\" display support"
+ depends on (FB = y) && PPC_PMAC && PPC32
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_MACMODES
+ help
+ This driver supports a frame buffer for the "platinum" graphics
+ adapter in some Power Macintoshes.
+
+config FB_VALKYRIE
+ bool "Apple \"valkyrie\" display support"
+ depends on (FB = y) && (MAC || (PPC_PMAC && PPC32))
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_MACMODES
+ help
+ This driver supports a frame buffer for the "valkyrie" graphics
+ adapter in some Power Macintoshes.
+
+config FB_CT65550
+ bool "Chips 65550 display support"
+ depends on (FB = y) && PPC32 && PCI
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the frame buffer device driver for the Chips & Technologies
+ 65550 graphics chip in PowerBooks.
+
+config FB_ASILIANT
+ bool "Asiliant (Chips) 69000 display support"
+ depends on (FB = y) && PCI
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the frame buffer device driver for the Asiliant 69030 chipset
+
+config FB_IMSTT
+ bool "IMS Twin Turbo display support"
+ depends on (FB = y) && PCI
+ select FB_CFB_IMAGEBLIT
+ select FB_MACMODES if PPC
+ help
+ The IMS Twin Turbo is a PCI-based frame buffer card bundled with
+ many Macintosh and compatible computers.
+
+config FB_VGA16
+ tristate "VGA 16-color graphics support"
+ depends on FB && (X86 || PPC)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select VGASTATE
+ select FONT_8x16 if FRAMEBUFFER_CONSOLE
+ help
+ This is the frame buffer device driver for VGA 16 color graphic
+ cards. Say Y if you have such a card.
+
+ To compile this driver as a module, choose M here: the
+ module will be called vga16fb.
+
+config FB_BF54X_LQ043
+ tristate "SHARP LQ043 TFT LCD (BF548 EZKIT)"
+ depends on FB && (BF54x) && !BF542
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the framebuffer device driver for a SHARP LQ043T1DG01 TFT LCD
+
+config FB_BFIN_T350MCQB
+ tristate "Varitronix COG-T350MCQB TFT LCD display (BF527 EZKIT)"
+ depends on FB && BLACKFIN
+ select BFIN_GPTIMERS
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the framebuffer device driver for a Varitronix VL-PS-COG-T350MCQB-01 display TFT LCD
+ This display is a QVGA 320x240 24-bit RGB display interfaced by an 8-bit wide PPI
+ It uses PPI[0..7] PPI_FS1, PPI_FS2 and PPI_CLK.
+
+config FB_BFIN_LQ035Q1
+ tristate "SHARP LQ035Q1DH02 TFT LCD"
+ depends on FB && BLACKFIN && SPI
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select BFIN_GPTIMERS
+ help
+ This is the framebuffer device driver for a SHARP LQ035Q1DH02 TFT display found on
+ the Blackfin Landscape LCD EZ-Extender Card.
+ This display is a QVGA 320x240 18-bit RGB display interfaced by an 16-bit wide PPI
+ It uses PPI[0..15] PPI_FS1, PPI_FS2 and PPI_CLK.
+
+ To compile this driver as a module, choose M here: the
+ module will be called bfin-lq035q1-fb.
+
+config FB_BF537_LQ035
+ tristate "SHARP LQ035 TFT LCD (BF537 STAMP)"
+ depends on FB && (BF534 || BF536 || BF537) && I2C_BLACKFIN_TWI
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select BFIN_GPTIMERS
+ help
+ This is the framebuffer device for a SHARP LQ035Q7DB03 TFT LCD
+ attached to a BF537.
+
+ To compile this driver as a module, choose M here: the
+ module will be called bf537-lq035.
+
+config FB_BFIN_7393
+ tristate "Blackfin ADV7393 Video encoder"
+ depends on FB && BLACKFIN
+ select I2C
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the framebuffer device for a ADV7393 video encoder
+ attached to a Blackfin on the PPI port.
+ If your Blackfin board has a ADV7393 select Y.
+
+ To compile this driver as a module, choose M here: the
+ module will be called bfin_adv7393fb.
+
+choice
+ prompt "Video mode support"
+ depends on FB_BFIN_7393
+ default NTSC
+
+config NTSC
+ bool 'NTSC 720x480'
+
+config PAL
+ bool 'PAL 720x576'
+
+config NTSC_640x480
+ bool 'NTSC 640x480 (Experimental)'
+
+config PAL_640x480
+ bool 'PAL 640x480 (Experimental)'
+
+config NTSC_YCBCR
+ bool 'NTSC 720x480 YCbCR input'
+
+config PAL_YCBCR
+ bool 'PAL 720x576 YCbCR input'
+
+endchoice
+
+choice
+ prompt "Size of ADV7393 frame buffer memory Single/Double Size"
+ depends on (FB_BFIN_7393)
+ default ADV7393_1XMEM
+
+config ADV7393_1XMEM
+ bool 'Single'
+
+config ADV7393_2XMEM
+ bool 'Double'
+endchoice
+
+config FB_STI
+ tristate "HP STI frame buffer device support"
+ depends on FB && PARISC
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select STI_CONSOLE
+ select VT
+ default y
+ ---help---
+ STI refers to the HP "Standard Text Interface" which is a set of
+ BIOS routines contained in a ROM chip in HP PA-RISC based machines.
+ Enabling this option will implement the linux framebuffer device
+ using calls to the STI BIOS routines for initialisation.
+
+ If you enable this option, you will get a planar framebuffer device
+ /dev/fb which will work on the most common HP graphic cards of the
+ NGLE family, including the artist chips (in the 7xx and Bxxx series),
+ HCRX, HCRX24, CRX, CRX24 and VisEG series.
+
+ It is safe to enable this option, so you should probably say "Y".
+
+config FB_MAC
+ bool "Generic Macintosh display support"
+ depends on (FB = y) && MAC
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_MACMODES
+
+config FB_HP300
+ bool
+ depends on (FB = y) && DIO
+ select FB_CFB_IMAGEBLIT
+ default y
+
+config FB_TGA
+ tristate "TGA/SFB+ framebuffer support"
+ depends on FB && (ALPHA || TC)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select BITREVERSE
+ ---help---
+ This is the frame buffer device driver for generic TGA and SFB+
+ graphic cards. These include DEC ZLXp-E1, -E2 and -E3 PCI cards,
+ also known as PBXGA-A, -B and -C, and DEC ZLX-E1, -E2 and -E3
+ TURBOchannel cards, also known as PMAGD-A, -B and -C.
+
+ Due to hardware limitations ZLX-E2 and E3 cards are not supported
+ for DECstation 5000/200 systems. Additionally due to firmware
+ limitations these cards may cause troubles with booting DECstation
+ 5000/240 and /260 systems, but are fully supported under Linux if
+ you manage to get it going. ;-)
+
+ Say Y if you have one of those.
+
+config FB_UVESA
+ tristate "Userspace VESA VGA graphics support"
+ depends on FB && CONNECTOR
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_MODE_HELPERS
+ help
+ This is the frame buffer driver for generic VBE 2.0 compliant
+ graphic cards. It can also take advantage of VBE 3.0 features,
+ such as refresh rate adjustment.
+
+ This driver generally provides more features than vesafb but
+ requires a userspace helper application called 'v86d'. See
+ <file:Documentation/fb/uvesafb.txt> for more information.
+
+ If unsure, say N.
+
+config FB_VESA
+ bool "VESA VGA graphics support"
+ depends on (FB = y) && X86
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_BOOT_VESA_SUPPORT
+ help
+ This is the frame buffer device driver for generic VESA 2.0
+ compliant graphic cards. The older VESA 1.2 cards are not supported.
+ You will get a boot time penguin logo at no additional cost. Please
+ read <file:Documentation/fb/vesafb.txt>. If unsure, say Y.
+
+config FB_EFI
+ bool "EFI-based Framebuffer Support"
+ depends on (FB = y) && X86 && EFI
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the EFI frame buffer device driver. If the firmware on
+ your platform is EFI 1.10 or UEFI 2.0, select Y to add support for
+ using the EFI framebuffer as your console.
+
+config FB_N411
+ tristate "N411 Apollo/Hecuba devkit support"
+ depends on FB && X86 && MMU
+ select FB_SYS_FILLRECT
+ select FB_SYS_COPYAREA
+ select FB_SYS_IMAGEBLIT
+ select FB_SYS_FOPS
+ select FB_DEFERRED_IO
+ select FB_HECUBA
+ help
+ This enables support for the Apollo display controller in its
+ Hecuba form using the n411 devkit.
+
+config FB_HGA
+ tristate "Hercules mono graphics support"
+ depends on FB && X86
+ help
+ Say Y here if you have a Hercules mono graphics card.
+
+ To compile this driver as a module, choose M here: the
+ module will be called hgafb.
+
+ As this card technology is at least 25 years old,
+ most people will answer N here.
+
+config FB_GBE
+ bool "SGI Graphics Backend frame buffer support"
+ depends on (FB = y) && SGI_IP32
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the frame buffer device driver for SGI Graphics Backend.
+ This chip is used in SGI O2 and Visual Workstation 320/540.
+
+config FB_GBE_MEM
+ int "Video memory size in MB"
+ depends on FB_GBE
+ default 4
+ help
+ This is the amount of memory reserved for the framebuffer,
+ which can be any value between 1MB and 8MB.
+
+config FB_SBUS
+ bool "SBUS and UPA framebuffers"
+ depends on (FB = y) && SPARC
+ help
+ Say Y if you want support for SBUS or UPA based frame buffer device.
+
+config FB_BW2
+ bool "BWtwo support"
+ depends on (FB = y) && (SPARC && FB_SBUS)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the frame buffer device driver for the BWtwo frame buffer.
+
+config FB_CG3
+ bool "CGthree support"
+ depends on (FB = y) && (SPARC && FB_SBUS)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the frame buffer device driver for the CGthree frame buffer.
+
+config FB_CG6
+ bool "CGsix (GX,TurboGX) support"
+ depends on (FB = y) && (SPARC && FB_SBUS)
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the frame buffer device driver for the CGsix (GX, TurboGX)
+ frame buffer.
+
+config FB_FFB
+ bool "Creator/Creator3D/Elite3D support"
+ depends on FB_SBUS && SPARC64
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the frame buffer device driver for the Creator, Creator3D,
+ and Elite3D graphics boards.
+
+config FB_TCX
+ bool "TCX (SS4/SS5 only) support"
+ depends on FB_SBUS
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the frame buffer device driver for the TCX 24/8bit frame
+ buffer.
+
+config FB_CG14
+ bool "CGfourteen (SX) support"
+ depends on FB_SBUS
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the frame buffer device driver for the CGfourteen frame
+ buffer on Desktop SPARCsystems with the SX graphics option.
+
+config FB_P9100
+ bool "P9100 (Sparcbook 3 only) support"
+ depends on FB_SBUS
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the frame buffer device driver for the P9100 card
+ supported on Sparcbook 3 machines.
+
+config FB_LEO
+ bool "Leo (ZX) support"
+ depends on FB_SBUS
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the frame buffer device driver for the SBUS-based Sun ZX
+ (leo) frame buffer cards.
+
+config FB_IGA
+ bool "IGA 168x display support"
+ depends on (FB = y) && SPARC32
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the framebuffer device for the INTERGRAPHICS 1680 and
+ successor frame buffer cards.
+
+config FB_XVR500
+ bool "Sun XVR-500 3DLABS Wildcat support"
+ depends on (FB = y) && PCI && SPARC64
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the framebuffer device for the Sun XVR-500 and similar
+ graphics cards based upon the 3DLABS Wildcat chipset. The driver
+ only works on sparc64 systems where the system firmware has
+ mostly initialized the card already. It is treated as a
+ completely dumb framebuffer device.
+
+config FB_XVR2500
+ bool "Sun XVR-2500 3DLABS Wildcat support"
+ depends on (FB = y) && PCI && SPARC64
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the framebuffer device for the Sun XVR-2500 and similar
+ graphics cards based upon the 3DLABS Wildcat chipset. The driver
+ only works on sparc64 systems where the system firmware has
+ mostly initialized the card already. It is treated as a
+ completely dumb framebuffer device.
+
+config FB_XVR1000
+ bool "Sun XVR-1000 support"
+ depends on (FB = y) && SPARC64
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the framebuffer device for the Sun XVR-1000 and similar
+ graphics cards. The driver only works on sparc64 systems where
+ the system firmware has mostly initialized the card already. It
+ is treated as a completely dumb framebuffer device.
+
+config FB_PVR2
+ tristate "NEC PowerVR 2 display support"
+ depends on FB && SH_DREAMCAST
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ ---help---
+ Say Y here if you have a PowerVR 2 card in your box. If you plan to
+ run linux on your Dreamcast, you will have to say Y here.
+ This driver may or may not work on other PowerVR 2 cards, but is
+ totally untested. Use at your own risk. If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called pvr2fb.
+
+ You can pass several parameters to the driver at boot time or at
+ module load time. The parameters look like "video=pvr2:XXX", where
+ the meaning of XXX can be found at the end of the main source file
+ (<file:drivers/video/pvr2fb.c>). Please see the file
+ <file:Documentation/fb/pvr2fb.txt>.
+
+config FB_OPENCORES
+ tristate "OpenCores VGA/LCD core 2.0 framebuffer support"
+ depends on FB && HAS_DMA
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This enables support for the OpenCores VGA/LCD core.
+
+ The OpenCores VGA/LCD core is typically used together with
+ softcore CPUs (e.g. OpenRISC or Microblaze) or hard processor
+ systems (e.g. Altera socfpga or Xilinx Zynq) on FPGAs.
+
+ The source code and specification for the core is available at
+ <http://opencores.org/project,vga_lcd>
+
+config FB_S1D13XXX
+ tristate "Epson S1D13XXX framebuffer support"
+ depends on FB
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ Support for S1D13XXX framebuffer device family (currently only
+ working with S1D13806). Product specs at
+ <http://vdc.epson.com/>
+
+config FB_ATMEL
+ tristate "AT91/AT32 LCD Controller support"
+ depends on FB && HAVE_FB_ATMEL
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_MODE_HELPERS
+ select VIDEOMODE_HELPERS
+ help
+ This enables support for the AT91/AT32 LCD Controller.
+
+config FB_INTSRAM
+ bool "Frame Buffer in internal SRAM"
+ depends on FB_ATMEL && ARCH_AT91SAM9261
+ help
+ Say Y if you want to map Frame Buffer in internal SRAM. Say N if you want
+ to let frame buffer in external SDRAM.
+
+config FB_ATMEL_STN
+ bool "Use a STN display with AT91/AT32 LCD Controller"
+ depends on FB_ATMEL && (MACH_AT91SAM9261EK || MACH_AT91SAM9G10EK)
+ default n
+ help
+ Say Y if you want to connect a STN LCD display to the AT91/AT32 LCD
+ Controller. Say N if you want to connect a TFT.
+
+ If unsure, say N.
+
+config FB_NVIDIA
+ tristate "nVidia Framebuffer Support"
+ depends on FB && PCI
+ select FB_BACKLIGHT if FB_NVIDIA_BACKLIGHT
+ select FB_MODE_HELPERS
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select BITREVERSE
+ select VGASTATE
+ help
+ This driver supports graphics boards with the nVidia chips, TNT
+ and newer. For very old chipsets, such as the RIVA128, then use
+ the rivafb.
+ Say Y if you have such a graphics board.
+
+ To compile this driver as a module, choose M here: the
+ module will be called nvidiafb.
+
+config FB_NVIDIA_I2C
+ bool "Enable DDC Support"
+ depends on FB_NVIDIA
+ select FB_DDC
+ help
+ This enables I2C support for nVidia Chipsets. This is used
+ only for getting EDID information from the attached display
+ allowing for robust video mode handling and switching.
+
+ Because fbdev-2.6 requires that drivers must be able to
+ independently validate video mode parameters, you should say Y
+ here.
+
+config FB_NVIDIA_DEBUG
+ bool "Lots of debug output"
+ depends on FB_NVIDIA
+ default n
+ help
+ Say Y here if you want the nVidia driver to output all sorts
+ of debugging information to provide to the maintainer when
+ something goes wrong.
+
+config FB_NVIDIA_BACKLIGHT
+ bool "Support for backlight control"
+ depends on FB_NVIDIA
+ default y
+ help
+ Say Y here if you want to control the backlight of your display.
+
+config FB_RIVA
+ tristate "nVidia Riva support"
+ depends on FB && PCI
+ select FB_BACKLIGHT if FB_RIVA_BACKLIGHT
+ select FB_MODE_HELPERS
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select BITREVERSE
+ select VGASTATE
+ help
+ This driver supports graphics boards with the nVidia Riva/Geforce
+ chips.
+ Say Y if you have such a graphics board.
+
+ To compile this driver as a module, choose M here: the
+ module will be called rivafb.
+
+config FB_RIVA_I2C
+ bool "Enable DDC Support"
+ depends on FB_RIVA
+ select FB_DDC
+ help
+ This enables I2C support for nVidia Chipsets. This is used
+ only for getting EDID information from the attached display
+ allowing for robust video mode handling and switching.
+
+ Because fbdev-2.6 requires that drivers must be able to
+ independently validate video mode parameters, you should say Y
+ here.
+
+config FB_RIVA_DEBUG
+ bool "Lots of debug output"
+ depends on FB_RIVA
+ default n
+ help
+ Say Y here if you want the Riva driver to output all sorts
+ of debugging information to provide to the maintainer when
+ something goes wrong.
+
+config FB_RIVA_BACKLIGHT
+ bool "Support for backlight control"
+ depends on FB_RIVA
+ default y
+ help
+ Say Y here if you want to control the backlight of your display.
+
+config FB_I740
+ tristate "Intel740 support"
+ depends on FB && PCI
+ select FB_MODE_HELPERS
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select VGASTATE
+ select FB_DDC
+ help
+ This driver supports graphics cards based on Intel740 chip.
+
+config FB_I810
+ tristate "Intel 810/815 support"
+ depends on FB && PCI && X86_32 && AGP_INTEL
+ select FB_MODE_HELPERS
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select VGASTATE
+ help
+ This driver supports the on-board graphics built in to the Intel 810
+ and 815 chipsets. Say Y if you have and plan to use such a board.
+
+ To compile this driver as a module, choose M here: the
+ module will be called i810fb.
+
+ For more information, please read
+ <file:Documentation/fb/intel810.txt>
+
+config FB_I810_GTF
+ bool "use VESA Generalized Timing Formula"
+ depends on FB_I810
+ help
+ If you say Y, then the VESA standard, Generalized Timing Formula
+ or GTF, will be used to calculate the required video timing values
+ per video mode. Since the GTF allows nondiscrete timings
+ (nondiscrete being a range of values as opposed to discrete being a
+ set of values), you'll be able to use any combination of horizontal
+ and vertical resolutions, and vertical refresh rates without having
+ to specify your own timing parameters. This is especially useful
+ to maximize the performance of an aging display, or if you just
+ have a display with nonstandard dimensions. A VESA compliant
+ monitor is recommended, but can still work with non-compliant ones.
+ If you need or want this, then select this option. The timings may
+ not be compliant with Intel's recommended values. Use at your own
+ risk.
+
+ If you say N, the driver will revert to discrete video timings
+ using a set recommended by Intel in their documentation.
+
+ If unsure, say N.
+
+config FB_I810_I2C
+ bool "Enable DDC Support"
+ depends on FB_I810 && FB_I810_GTF
+ select FB_DDC
+ help
+
+config FB_LE80578
+ tristate "Intel LE80578 (Vermilion) support"
+ depends on FB && PCI && X86
+ select FB_MODE_HELPERS
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This driver supports the LE80578 (Vermilion Range) chipset
+
+config FB_CARILLO_RANCH
+ tristate "Intel Carillo Ranch support"
+ depends on FB_LE80578 && FB && PCI && X86
+ help
+ This driver supports the LE80578 (Carillo Ranch) board
+
+config FB_INTEL
+ tristate "Intel 830M/845G/852GM/855GM/865G/915G/945G/945GM/965G/965GM support"
+ depends on FB && PCI && X86 && AGP_INTEL && EXPERT
+ select FB_MODE_HELPERS
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_BOOT_VESA_SUPPORT if FB_INTEL = y
+ depends on !DRM_I915
+ help
+ This driver supports the on-board graphics built in to the Intel
+ 830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/965G/965GM chipsets.
+ Say Y if you have and plan to use such a board.
+
+ To make FB_INTELFB=Y work you need to say AGP_INTEL=y too.
+
+ To compile this driver as a module, choose M here: the
+ module will be called intelfb.
+
+ For more information, please read <file:Documentation/fb/intelfb.txt>
+
+config FB_INTEL_DEBUG
+ bool "Intel driver Debug Messages"
+ depends on FB_INTEL
+ ---help---
+ Say Y here if you want the Intel driver to output all sorts
+ of debugging information to provide to the maintainer when
+ something goes wrong.
+
+config FB_INTEL_I2C
+ bool "DDC/I2C for Intel framebuffer support"
+ depends on FB_INTEL
+ select FB_DDC
+ default y
+ help
+ Say Y here if you want DDC/I2C support for your on-board Intel graphics.
+
+config FB_MATROX
+ tristate "Matrox acceleration"
+ depends on FB && PCI
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_TILEBLITTING
+ select FB_MACMODES if PPC_PMAC
+ ---help---
+ Say Y here if you have a Matrox Millennium, Matrox Millennium II,
+ Matrox Mystique, Matrox Mystique 220, Matrox Productiva G100, Matrox
+ Mystique G200, Matrox Millennium G200, Matrox Marvel G200 video,
+ Matrox G400, G450 or G550 card in your box.
+
+ To compile this driver as a module, choose M here: the
+ module will be called matroxfb.
+
+ You can pass several parameters to the driver at boot time or at
+ module load time. The parameters look like "video=matroxfb:XXX", and
+ are described in <file:Documentation/fb/matroxfb.txt>.
+
+config FB_MATROX_MILLENIUM
+ bool "Millennium I/II support"
+ depends on FB_MATROX
+ help
+ Say Y here if you have a Matrox Millennium or Matrox Millennium II
+ video card. If you select "Advanced lowlevel driver options" below,
+ you should check 4 bpp packed pixel, 8 bpp packed pixel, 16 bpp
+ packed pixel, 24 bpp packed pixel and 32 bpp packed pixel. You can
+ also use font widths different from 8.
+
+config FB_MATROX_MYSTIQUE
+ bool "Mystique support"
+ depends on FB_MATROX
+ help
+ Say Y here if you have a Matrox Mystique or Matrox Mystique 220
+ video card. If you select "Advanced lowlevel driver options" below,
+ you should check 8 bpp packed pixel, 16 bpp packed pixel, 24 bpp
+ packed pixel and 32 bpp packed pixel. You can also use font widths
+ different from 8.
+
+config FB_MATROX_G
+ bool "G100/G200/G400/G450/G550 support"
+ depends on FB_MATROX
+ ---help---
+ Say Y here if you have a Matrox G100, G200, G400, G450 or G550 based
+ video card. If you select "Advanced lowlevel driver options", you
+ should check 8 bpp packed pixel, 16 bpp packed pixel, 24 bpp packed
+ pixel and 32 bpp packed pixel. You can also use font widths
+ different from 8.
+
+ If you need support for G400 secondary head, you must say Y to
+ "Matrox I2C support" and "G400 second head support" right below.
+ G450/G550 secondary head and digital output are supported without
+ additional modules.
+
+ The driver starts in monitor mode. You must use the matroxset tool
+ (available at <ftp://platan.vc.cvut.cz/pub/linux/matrox-latest/>) to
+ swap primary and secondary head outputs, or to change output mode.
+ Secondary head driver always start in 640x480 resolution and you
+ must use fbset to change it.
+
+ Do not forget that second head supports only 16 and 32 bpp
+ packed pixels, so it is a good idea to compile them into the kernel
+ too. You can use only some font widths, as the driver uses generic
+ painting procedures (the secondary head does not use acceleration
+ engine).
+
+ G450/G550 hardware can display TV picture only from secondary CRTC,
+ and it performs no scaling, so picture must have 525 or 625 lines.
+
+config FB_MATROX_I2C
+ tristate "Matrox I2C support"
+ depends on FB_MATROX
+ select FB_DDC
+ ---help---
+ This drivers creates I2C buses which are needed for accessing the
+ DDC (I2C) bus present on all Matroxes, an I2C bus which
+ interconnects Matrox optional devices, like MGA-TVO on G200 and
+ G400, and the secondary head DDC bus, present on G400 only.
+
+ You can say Y or M here if you want to experiment with monitor
+ detection code. You must say Y or M here if you want to use either
+ second head of G400 or MGA-TVO on G200 or G400.
+
+ If you compile it as module, it will create a module named
+ i2c-matroxfb.
+
+config FB_MATROX_MAVEN
+ tristate "G400 second head support"
+ depends on FB_MATROX_G && FB_MATROX_I2C
+ ---help---
+ WARNING !!! This support does not work with G450 !!!
+
+ Say Y or M here if you want to use a secondary head (meaning two
+ monitors in parallel) on G400 or MGA-TVO add-on on G200. Secondary
+ head is not compatible with accelerated XFree 3.3.x SVGA servers -
+ secondary head output is blanked while you are in X. With XFree
+ 3.9.17 preview you can use both heads if you use SVGA over fbdev or
+ the fbdev driver on first head and the fbdev driver on second head.
+
+ If you compile it as module, two modules are created,
+ matroxfb_crtc2 and matroxfb_maven. Matroxfb_maven is needed for
+ both G200 and G400, matroxfb_crtc2 is needed only by G400. You must
+ also load i2c-matroxfb to get it to run.
+
+ The driver starts in monitor mode and you must use the matroxset
+ tool (available at
+ <ftp://platan.vc.cvut.cz/pub/linux/matrox-latest/>) to switch it to
+ PAL or NTSC or to swap primary and secondary head outputs.
+ Secondary head driver also always start in 640x480 resolution, you
+ must use fbset to change it.
+
+ Also do not forget that second head supports only 16 and 32 bpp
+ packed pixels, so it is a good idea to compile them into the kernel
+ too. You can use only some font widths, as the driver uses generic
+ painting procedures (the secondary head does not use acceleration
+ engine).
+
+config FB_RADEON
+ tristate "ATI Radeon display support"
+ depends on FB && PCI
+ select FB_BACKLIGHT if FB_RADEON_BACKLIGHT
+ select FB_MODE_HELPERS
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_MACMODES if PPC_OF
+ help
+ Choose this option if you want to use an ATI Radeon graphics card as
+ a framebuffer device. There are both PCI and AGP versions. You
+ don't need to choose this to run the Radeon in plain VGA mode.
+
+ There is a product page at
+ http://products.amd.com/en-us/GraphicCardResult.aspx
+
+config FB_RADEON_I2C
+ bool "DDC/I2C for ATI Radeon support"
+ depends on FB_RADEON
+ select FB_DDC
+ default y
+ help
+ Say Y here if you want DDC/I2C support for your Radeon board.
+
+config FB_RADEON_BACKLIGHT
+ bool "Support for backlight control"
+ depends on FB_RADEON
+ default y
+ help
+ Say Y here if you want to control the backlight of your display.
+
+config FB_RADEON_DEBUG
+ bool "Lots of debug output from Radeon driver"
+ depends on FB_RADEON
+ default n
+ help
+ Say Y here if you want the Radeon driver to output all sorts
+ of debugging information to provide to the maintainer when
+ something goes wrong.
+
+config FB_ATY128
+ tristate "ATI Rage128 display support"
+ depends on FB && PCI
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_BACKLIGHT if FB_ATY128_BACKLIGHT
+ select FB_MACMODES if PPC_PMAC
+ help
+ This driver supports graphics boards with the ATI Rage128 chips.
+ Say Y if you have such a graphics board and read
+ <file:Documentation/fb/aty128fb.txt>.
+
+ To compile this driver as a module, choose M here: the
+ module will be called aty128fb.
+
+config FB_ATY128_BACKLIGHT
+ bool "Support for backlight control"
+ depends on FB_ATY128
+ default y
+ help
+ Say Y here if you want to control the backlight of your display.
+
+config FB_ATY
+ tristate "ATI Mach64 display support" if PCI || ATARI
+ depends on FB && !SPARC32
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_BACKLIGHT if FB_ATY_BACKLIGHT
+ select FB_MACMODES if PPC
+ help
+ This driver supports graphics boards with the ATI Mach64 chips.
+ Say Y if you have such a graphics board.
+
+ To compile this driver as a module, choose M here: the
+ module will be called atyfb.
+
+config FB_ATY_CT
+ bool "Mach64 CT/VT/GT/LT (incl. 3D RAGE) support"
+ depends on PCI && FB_ATY
+ default y if SPARC64 && PCI
+ help
+ Say Y here to support use of ATI's 64-bit Rage boards (or other
+ boards based on the Mach64 CT, VT, GT, and LT chipsets) as a
+ framebuffer device. The ATI product support page for these boards
+ is at <http://support.ati.com/products/pc/mach64/mach64.html>.
+
+config FB_ATY_GENERIC_LCD
+ bool "Mach64 generic LCD support"
+ depends on FB_ATY_CT
+ help
+ Say Y if you have a laptop with an ATI Rage LT PRO, Rage Mobility,
+ Rage XC, or Rage XL chipset.
+
+config FB_ATY_GX
+ bool "Mach64 GX support" if PCI
+ depends on FB_ATY
+ default y if ATARI
+ help
+ Say Y here to support use of the ATI Mach64 Graphics Expression
+ board (or other boards based on the Mach64 GX chipset) as a
+ framebuffer device. The ATI product support page for these boards
+ is at
+ <http://support.ati.com/products/pc/mach64/graphics_xpression.html>.
+
+config FB_ATY_BACKLIGHT
+ bool "Support for backlight control"
+ depends on FB_ATY
+ default y
+ help
+ Say Y here if you want to control the backlight of your display.
+
+config FB_S3
+ tristate "S3 Trio/Virge support"
+ depends on FB && PCI
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_TILEBLITTING
+ select FB_SVGALIB
+ select VGASTATE
+ select FONT_8x16 if FRAMEBUFFER_CONSOLE
+ ---help---
+ Driver for graphics boards with S3 Trio / S3 Virge chip.
+
+config FB_S3_DDC
+ bool "DDC for S3 support"
+ depends on FB_S3
+ select FB_DDC
+ default y
+ help
+ Say Y here if you want DDC support for your S3 graphics card.
+
+config FB_SAVAGE
+ tristate "S3 Savage support"
+ depends on FB && PCI
+ select FB_MODE_HELPERS
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select VGASTATE
+ help
+ This driver supports notebooks and computers with S3 Savage PCI/AGP
+ chips.
+
+ Say Y if you have such a graphics card.
+
+ To compile this driver as a module, choose M here; the module
+ will be called savagefb.
+
+config FB_SAVAGE_I2C
+ bool "Enable DDC2 Support"
+ depends on FB_SAVAGE
+ select FB_DDC
+ help
+ This enables I2C support for S3 Savage Chipsets. This is used
+ only for getting EDID information from the attached display
+ allowing for robust video mode handling and switching.
+
+ Because fbdev-2.6 requires that drivers must be able to
+ independently validate video mode parameters, you should say Y
+ here.
+
+config FB_SAVAGE_ACCEL
+ bool "Enable Console Acceleration"
+ depends on FB_SAVAGE
+ default n
+ help
+ This option will compile in console acceleration support. If
+ the resulting framebuffer console has bothersome glitches, then
+ choose N here.
+
+config FB_SIS
+ tristate "SiS/XGI display support"
+ depends on FB && PCI
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_BOOT_VESA_SUPPORT if FB_SIS = y
+ help
+ This is the frame buffer device driver for the SiS 300, 315, 330
+ and 340 series as well as XGI V3XT, V5, V8, Z7 graphics chipsets.
+ Specs available at <http://www.sis.com> and <http://www.xgitech.com>.
+
+ To compile this driver as a module, choose M here; the module
+ will be called sisfb.
+
+config FB_SIS_300
+ bool "SiS 300 series support"
+ depends on FB_SIS
+ help
+ Say Y here to support use of the SiS 300/305, 540, 630 and 730.
+
+config FB_SIS_315
+ bool "SiS 315/330/340 series and XGI support"
+ depends on FB_SIS
+ help
+ Say Y here to support use of the SiS 315, 330 and 340 series
+ (315/H/PRO, 55x, 650, 651, 740, 330, 661, 741, 760, 761) as well
+ as XGI V3XT, V5, V8 and Z7.
+
+config FB_VIA
+ tristate "VIA UniChrome (Pro) and Chrome9 display support"
+ depends on FB && PCI && X86
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select I2C_ALGOBIT
+ select I2C
+ select GPIOLIB
+ help
+ This is the frame buffer device driver for Graphics chips of VIA
+ UniChrome (Pro) Family (CLE266,PM800/CN400,P4M800CE/P4M800Pro/
+ CN700/VN800,CX700/VX700,P4M890) and Chrome9 Family (K8M890,CN896
+ /P4M900,VX800)
+ Say Y if you have a VIA UniChrome graphics board.
+
+ To compile this driver as a module, choose M here: the
+ module will be called viafb.
+
+if FB_VIA
+
+config FB_VIA_DIRECT_PROCFS
+ bool "direct hardware access via procfs (DEPRECATED)(DANGEROUS)"
+ depends on FB_VIA
+ default n
+ help
+ Allow direct hardware access to some output registers via procfs.
+ This is dangerous but may provide the only chance to get the
+ correct output device configuration.
+ Its use is strongly discouraged.
+
+config FB_VIA_X_COMPATIBILITY
+ bool "X server compatibility"
+ depends on FB_VIA
+ default n
+ help
+ This option reduces the functionality (power saving, ...) of the
+ framebuffer to avoid negative impact on the OpenChrome X server.
+ If you use any X server other than fbdev you should enable this
+ otherwise it should be safe to disable it and allow using all
+ features.
+
+endif
+
+config FB_NEOMAGIC
+ tristate "NeoMagic display support"
+ depends on FB && PCI
+ select FB_MODE_HELPERS
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select VGASTATE
+ help
+ This driver supports notebooks with NeoMagic PCI chips.
+ Say Y if you have such a graphics card.
+
+ To compile this driver as a module, choose M here: the
+ module will be called neofb.
+
+config FB_KYRO
+ tristate "IMG Kyro support"
+ depends on FB && PCI
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ Say Y here if you have a STG4000 / Kyro / PowerVR 3 based
+ graphics board.
+
+ To compile this driver as a module, choose M here: the
+ module will be called kyrofb.
+
+config FB_3DFX
+ tristate "3Dfx Banshee/Voodoo3/Voodoo5 display support"
+ depends on FB && PCI
+ select FB_CFB_IMAGEBLIT
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_MODE_HELPERS
+ help
+ This driver supports graphics boards with the 3Dfx Banshee,
+ Voodoo3 or VSA-100 (aka Voodoo4/5) chips. Say Y if you have
+ such a graphics board.
+
+ To compile this driver as a module, choose M here: the
+ module will be called tdfxfb.
+
+config FB_3DFX_ACCEL
+ bool "3Dfx Acceleration functions"
+ depends on FB_3DFX
+ ---help---
+ This will compile the 3Dfx Banshee/Voodoo3/VSA-100 frame buffer
+ device driver with acceleration functions.
+
+config FB_3DFX_I2C
+ bool "Enable DDC/I2C support"
+ depends on FB_3DFX
+ select FB_DDC
+ default y
+ help
+ Say Y here if you want DDC/I2C support for your 3dfx Voodoo3.
+
+config FB_VOODOO1
+ tristate "3Dfx Voodoo Graphics (sst1) support"
+ depends on FB && PCI
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ ---help---
+ Say Y here if you have a 3Dfx Voodoo Graphics (Voodoo1/sst1) or
+ Voodoo2 (cvg) based graphics card.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sstfb.
+
+ WARNING: Do not use any application that uses the 3D engine
+ (namely glide) while using this driver.
+ Please read the <file:Documentation/fb/sstfb.txt> for supported
+ options and other important info support.
+
+config FB_VT8623
+ tristate "VIA VT8623 support"
+ depends on FB && PCI
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_TILEBLITTING
+ select FB_SVGALIB
+ select VGASTATE
+ select FONT_8x16 if FRAMEBUFFER_CONSOLE
+ ---help---
+ Driver for CastleRock integrated graphics core in the
+ VIA VT8623 [Apollo CLE266] chipset.
+
+config FB_TRIDENT
+ tristate "Trident/CyberXXX/CyberBlade support"
+ depends on FB && PCI
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ ---help---
+ This is the frame buffer device driver for Trident PCI/AGP chipsets.
+ Supported chipset families are TGUI 9440/96XX, 3DImage, Blade3D
+ and Blade XP.
+ There are also integrated versions of these chips called CyberXXXX,
+ CyberImage or CyberBlade. These chips are mostly found in laptops
+ but also on some motherboards including early VIA EPIA motherboards.
+ For more information, read <file:Documentation/fb/tridentfb.txt>
+
+ Say Y if you have such a graphics board.
+
+ To compile this driver as a module, choose M here: the
+ module will be called tridentfb.
+
+config FB_ARK
+ tristate "ARK 2000PV support"
+ depends on FB && PCI
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_TILEBLITTING
+ select FB_SVGALIB
+ select VGASTATE
+ select FONT_8x16 if FRAMEBUFFER_CONSOLE
+ ---help---
+ Driver for PCI graphics boards with ARK 2000PV chip
+ and ICS 5342 RAMDAC.
+
+config FB_PM3
+ tristate "Permedia3 support"
+ depends on FB && PCI
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the frame buffer device driver for the 3DLabs Permedia3
+ chipset, used in Formac ProFormance III, 3DLabs Oxygen VX1 &
+ similar boards, 3DLabs Permedia3 Create!, Appian Jeronimo 2000
+ and maybe other boards.
+
+config FB_CARMINE
+ tristate "Fujitsu carmine frame buffer support"
+ depends on FB && PCI
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the frame buffer device driver for the Fujitsu Carmine chip.
+ The driver provides two independent frame buffer devices.
+
+choice
+ depends on FB_CARMINE
+ prompt "DRAM timing"
+ default FB_CARMINE_DRAM_EVAL
+
+config FB_CARMINE_DRAM_EVAL
+ bool "Eval board timings"
+ help
+ Use timings which work on the eval card.
+
+config CARMINE_DRAM_CUSTOM
+ bool "Custom board timings"
+ help
+ Use custom board timings.
+endchoice
+
+config FB_AU1100
+ bool "Au1100 LCD Driver"
+ depends on (FB = y) && MIPS_ALCHEMY
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the framebuffer driver for the AMD Au1100 SOC. It can drive
+ various panels and CRTs by passing in kernel cmd line option
+ au1100fb:panel=<name>.
+
+config FB_AU1200
+ bool "Au1200/Au1300 LCD Driver"
+ depends on (FB = y) && MIPS_ALCHEMY
+ select FB_SYS_FILLRECT
+ select FB_SYS_COPYAREA
+ select FB_SYS_IMAGEBLIT
+ select FB_SYS_FOPS
+ help
+ This is the framebuffer driver for the Au1200/Au1300 SOCs.
+ It can drive various panels and CRTs by passing in kernel cmd line
+ option au1200fb:panel=<name>.
+
+config FB_VT8500
+ bool "VIA VT8500 framebuffer support"
+ depends on (FB = y) && ARM && ARCH_VT8500
+ select FB_SYS_FILLRECT if (!FB_WMT_GE_ROPS)
+ select FB_SYS_COPYAREA if (!FB_WMT_GE_ROPS)
+ select FB_SYS_IMAGEBLIT
+ select FB_MODE_HELPERS
+ select VIDEOMODE_HELPERS
+ help
+ This is the framebuffer driver for VIA VT8500 integrated LCD
+ controller.
+
+config FB_WM8505
+ bool "Wondermedia WM8xxx-series frame buffer support"
+ depends on (FB = y) && ARM && ARCH_VT8500
+ select FB_SYS_FILLRECT if (!FB_WMT_GE_ROPS)
+ select FB_SYS_COPYAREA if (!FB_WMT_GE_ROPS)
+ select FB_SYS_IMAGEBLIT
+ select FB_MODE_HELPERS
+ select VIDEOMODE_HELPERS
+ help
+ This is the framebuffer driver for WonderMedia WM8xxx-series
+ integrated LCD controller. This driver covers the WM8505, WM8650
+ and WM8850 SoCs.
+
+config FB_WMT_GE_ROPS
+ bool "VT8500/WM8xxx accelerated raster ops support"
+ depends on (FB = y) && (FB_VT8500 || FB_WM8505)
+ default n
+ help
+ This adds support for accelerated raster operations on the
+ VIA VT8500 and Wondermedia 85xx series SoCs.
+
+source "drivers/video/fbdev/geode/Kconfig"
+
+config FB_HIT
+ tristate "HD64461 Frame Buffer support"
+ depends on FB && HD64461
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the frame buffer device driver for the Hitachi HD64461 LCD
+ frame buffer card.
+
+config FB_PMAG_AA
+ bool "PMAG-AA TURBOchannel framebuffer support"
+ depends on (FB = y) && TC
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ Support for the PMAG-AA TURBOchannel framebuffer card (1280x1024x1)
+ used mainly in the MIPS-based DECstation series.
+
+config FB_PMAG_BA
+ tristate "PMAG-BA TURBOchannel framebuffer support"
+ depends on FB && TC
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ Support for the PMAG-BA TURBOchannel framebuffer card (1024x864x8)
+ used mainly in the MIPS-based DECstation series.
+
+config FB_PMAGB_B
+ tristate "PMAGB-B TURBOchannel framebuffer support"
+ depends on FB && TC
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ Support for the PMAGB-B TURBOchannel framebuffer card used mainly
+ in the MIPS-based DECstation series. The card is currently only
+ supported in 1280x1024x8 mode.
+
+config FB_MAXINE
+ bool "Maxine (Personal DECstation) onboard framebuffer support"
+ depends on (FB = y) && MACH_DECSTATION
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ Support for the onboard framebuffer (1024x768x8) in the Personal
+ DECstation series (Personal DECstation 5000/20, /25, /33, /50,
+ Codename "Maxine").
+
+config FB_G364
+ bool "G364 frame buffer support"
+ depends on (FB = y) && (MIPS_MAGNUM_4000 || OLIVETTI_M700)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ The G364 driver is the framebuffer used in MIPS Magnum 4000 and
+ Olivetti M700-10 systems.
+
+config FB_68328
+ bool "Motorola 68328 native frame buffer support"
+ depends on (FB = y) && (M68328 || M68EZ328 || M68VZ328)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ Say Y here if you want to support the built-in frame buffer of
+ the Motorola 68328 CPU family.
+
+config FB_PXA168
+ tristate "PXA168/910 LCD framebuffer support"
+ depends on FB && (CPU_PXA168 || CPU_PXA910)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ ---help---
+ Frame buffer driver for the built-in LCD controller in the Marvell
+ MMP processor.
+
+config FB_PXA
+ tristate "PXA LCD framebuffer support"
+ depends on FB && ARCH_PXA
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ ---help---
+ Frame buffer driver for the built-in LCD controller in the Intel
+ PXA2x0 processor.
+
+ This driver is also available as a module ( = code which can be
+ inserted and removed from the running kernel whenever you want). The
+ module will be called pxafb. If you want to compile it as a module,
+ say M here and read <file:Documentation/kbuild/modules.txt>.
+
+ If unsure, say N.
+
+config FB_PXA_OVERLAY
+ bool "Support PXA27x/PXA3xx Overlay(s) as framebuffer"
+ default n
+ depends on FB_PXA && (PXA27x || PXA3xx)
+
+config FB_PXA_SMARTPANEL
+ bool "PXA Smartpanel LCD support"
+ default n
+ depends on FB_PXA
+
+config FB_PXA_PARAMETERS
+ bool "PXA LCD command line parameters"
+ default n
+ depends on FB_PXA
+ ---help---
+ Enable the use of kernel command line or module parameters
+ to configure the physical properties of the LCD panel when
+ using the PXA LCD driver.
+
+ This option allows you to override the panel parameters
+ supplied by the platform in order to support multiple
+ different models of flatpanel. If you will only be using a
+ single model of flatpanel then you can safely leave this
+ option disabled.
+
+ <file:Documentation/fb/pxafb.txt> describes the available parameters.
+
+config PXA3XX_GCU
+ tristate "PXA3xx 2D graphics accelerator driver"
+ depends on FB_PXA
+ help
+ Kernelspace driver for the 2D graphics controller unit (GCU)
+ found on PXA3xx processors. There is a counterpart driver in the
+ DirectFB suite, see http://www.directfb.org/
+
+ If you compile this as a module, it will be called pxa3xx_gcu.
+
+config FB_MBX
+ tristate "2700G LCD framebuffer support"
+ depends on FB && ARCH_PXA
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ ---help---
+ Framebuffer driver for the Intel 2700G (Marathon) Graphics
+ Accelerator
+
+config FB_MBX_DEBUG
+ bool "Enable debugging info via debugfs"
+ depends on FB_MBX && DEBUG_FS
+ default n
+ ---help---
+ Enable this if you want debugging information using the debug
+ filesystem (debugfs)
+
+ If unsure, say N.
+
+config FB_FSL_DIU
+ tristate "Freescale DIU framebuffer support"
+ depends on FB && FSL_SOC
+ select FB_MODE_HELPERS
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select PPC_LIB_RHEAP
+ ---help---
+ Framebuffer driver for the Freescale SoC DIU
+
+config FB_W100
+ tristate "W100 frame buffer support"
+ depends on FB && ARCH_PXA
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ ---help---
+ Frame buffer driver for the w100 as found on the Sharp SL-Cxx series.
+ It can also drive the w3220 chip found on iPAQ hx4700.
+
+ This driver is also available as a module ( = code which can be
+ inserted and removed from the running kernel whenever you want). The
+ module will be called w100fb. If you want to compile it as a module,
+ say M here and read <file:Documentation/kbuild/modules.txt>.
+
+ If unsure, say N.
+
+config FB_SH_MOBILE_LCDC
+ tristate "SuperH Mobile LCDC framebuffer support"
+ depends on FB && (SUPERH || ARCH_SHMOBILE) && HAVE_CLK
+ select FB_SYS_FILLRECT
+ select FB_SYS_COPYAREA
+ select FB_SYS_IMAGEBLIT
+ select FB_SYS_FOPS
+ select FB_DEFERRED_IO
+ select FB_BACKLIGHT
+ select SH_MIPI_DSI if SH_LCD_MIPI_DSI
+ ---help---
+ Frame buffer driver for the on-chip SH-Mobile LCD controller.
+
+config FB_SH_MOBILE_HDMI
+ tristate "SuperH Mobile HDMI controller support"
+ depends on FB_SH_MOBILE_LCDC
+ select FB_MODE_HELPERS
+ select SOUND
+ select SND
+ select SND_SOC
+ ---help---
+ Driver for the on-chip SH-Mobile HDMI controller.
+
+config FB_TMIO
+ tristate "Toshiba Mobile IO FrameBuffer support"
+ depends on FB && MFD_CORE
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ ---help---
+ Frame buffer driver for the Toshiba Mobile IO integrated as found
+ on the Sharp SL-6000 series
+
+ This driver is also available as a module ( = code which can be
+ inserted and removed from the running kernel whenever you want). The
+ module will be called tmiofb. If you want to compile it as a module,
+ say M here and read <file:Documentation/kbuild/modules.txt>.
+
+ If unsure, say N.
+
+config FB_TMIO_ACCELL
+ bool "tmiofb acceleration"
+ depends on FB_TMIO
+ default y
+
+config FB_S3C
+ tristate "Samsung S3C framebuffer support"
+ depends on FB && (CPU_S3C2416 || ARCH_S3C64XX || ARCH_S5P64X0 || \
+ ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ ---help---
+ Frame buffer driver for the built-in FB controller in the Samsung
+ SoC line from the S3C2443 onwards, including the S3C2416, S3C2450,
+ and the S3C64XX series such as the S3C6400 and S3C6410.
+
+ These chips all have the same basic framebuffer design with the
+ actual capabilities depending on the chip. For instance the S3C6400
+ and S3C6410 support 4 hardware windows whereas the S3C24XX series
+ currently only have two.
+
+ Currently the support is only for the S3C6400 and S3C6410 SoCs.
+
+config FB_S3C_DEBUG_REGWRITE
+ bool "Debug register writes"
+ depends on FB_S3C
+ ---help---
+ Show all register writes via pr_debug()
+
+config FB_S3C2410
+ tristate "S3C2410 LCD framebuffer support"
+ depends on FB && ARCH_S3C24XX
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ ---help---
+ Frame buffer driver for the built-in LCD controller in the Samsung
+ S3C2410 processor.
+
+ This driver is also available as a module ( = code which can be
+ inserted and removed from the running kernel whenever you want). The
+ module will be called s3c2410fb. If you want to compile it as a module,
+ say M here and read <file:Documentation/kbuild/modules.txt>.
+
+ If unsure, say N.
+config FB_S3C2410_DEBUG
+ bool "S3C2410 lcd debug messages"
+ depends on FB_S3C2410
+ help
+ Turn on debugging messages. Note that you can set/unset at run time
+ through sysfs
+
+config FB_NUC900
+ bool "NUC900 LCD framebuffer support"
+ depends on FB && ARCH_W90X900
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ ---help---
+ Frame buffer driver for the built-in LCD controller in the Nuvoton
+ NUC900 processor
+
+config GPM1040A0_320X240
+ bool "Giantplus Technology GPM1040A0 320x240 Color TFT LCD"
+ depends on FB_NUC900
+
+config FB_SM501
+ tristate "Silicon Motion SM501 framebuffer support"
+ depends on FB && MFD_SM501
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ ---help---
+ Frame buffer driver for the CRT and LCD controllers in the Silicon
+ Motion SM501.
+
+ This driver is also available as a module ( = code which can be
+ inserted and removed from the running kernel whenever you want). The
+ module will be called sm501fb. If you want to compile it as a module,
+ say M here and read <file:Documentation/kbuild/modules.txt>.
+
+ If unsure, say N.
+
+config FB_SMSCUFX
+ tristate "SMSC UFX6000/7000 USB Framebuffer support"
+ depends on FB && USB
+ select FB_MODE_HELPERS
+ select FB_SYS_FILLRECT
+ select FB_SYS_COPYAREA
+ select FB_SYS_IMAGEBLIT
+ select FB_SYS_FOPS
+ select FB_DEFERRED_IO
+ ---help---
+ This is a kernel framebuffer driver for SMSC UFX USB devices.
+ Supports fbdev clients like xf86-video-fbdev, kdrive, fbi, and
+ mplayer -vo fbdev. Supports both UFX6000 (USB 2.0) and UFX7000
+ (USB 3.0) devices.
+ To compile as a module, choose M here: the module name is smscufx.
+
+config FB_UDL
+ tristate "Displaylink USB Framebuffer support"
+ depends on FB && USB
+ select FB_MODE_HELPERS
+ select FB_SYS_FILLRECT
+ select FB_SYS_COPYAREA
+ select FB_SYS_IMAGEBLIT
+ select FB_SYS_FOPS
+ select FB_DEFERRED_IO
+ ---help---
+ This is a kernel framebuffer driver for DisplayLink USB devices.
+ Supports fbdev clients like xf86-video-fbdev, kdrive, fbi, and
+ mplayer -vo fbdev. Supports all USB 2.0 era DisplayLink devices.
+ To compile as a module, choose M here: the module name is udlfb.
+
+config FB_IBM_GXT4500
+ tristate "Framebuffer support for IBM GXT4000P/4500P/6000P/6500P adaptors"
+ depends on FB && PPC
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ ---help---
+ Say Y here to enable support for the IBM GXT4000P/6000P and
+ GXT4500P/6500P display adaptor based on Raster Engine RC1000,
+ found on some IBM System P (pSeries) machines. This driver
+ doesn't use Geometry Engine GT1000.
+
+config FB_PS3
+ tristate "PS3 GPU framebuffer driver"
+ depends on FB && PS3_PS3AV
+ select FB_SYS_FILLRECT
+ select FB_SYS_COPYAREA
+ select FB_SYS_IMAGEBLIT
+ select FB_SYS_FOPS
+ select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE
+ ---help---
+ Include support for the virtual frame buffer in the PS3 platform.
+
+config FB_PS3_DEFAULT_SIZE_M
+ int "PS3 default frame buffer size (in MiB)"
+ depends on FB_PS3
+ default 9
+ ---help---
+ This is the default size (in MiB) of the virtual frame buffer in
+ the PS3.
+ The default value can be overridden on the kernel command line
+ using the "ps3fb" option (e.g. "ps3fb=9M");
+
+config FB_XILINX
+ tristate "Xilinx frame buffer support"
+ depends on FB && (XILINX_VIRTEX || MICROBLAZE || ARCH_ZYNQ)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ ---help---
+ Include support for the Xilinx ML300/ML403 reference design
+ framebuffer. ML300 carries a 640*480 LCD display on the board,
+ ML403 uses a standard DB15 VGA connector.
+
+config FB_GOLDFISH
+ tristate "Goldfish Framebuffer"
+ depends on FB && HAS_DMA
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ ---help---
+ Framebuffer driver for Goldfish Virtual Platform
+
+config FB_COBALT
+ tristate "Cobalt server LCD frame buffer support"
+ depends on FB && (MIPS_COBALT || MIPS_SEAD3)
+
+config FB_SH7760
+ bool "SH7760/SH7763/SH7720/SH7721 LCDC support"
+ depends on FB && (CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7763 \
+ || CPU_SUBTYPE_SH7720 || CPU_SUBTYPE_SH7721)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ ---help---
+ Support for the SH7760/SH7763/SH7720/SH7721 integrated
+ (D)STN/TFT LCD Controller.
+ Supports display resolutions up to 1024x1024 pixel, grayscale and
+ color operation, with depths ranging from 1 bpp to 8 bpp monochrome
+ and 8, 15 or 16 bpp color; 90 degrees clockwise display rotation for
+ panels <= 320 pixel horizontal resolution.
+
+config FB_DA8XX
+ tristate "DA8xx/OMAP-L1xx/AM335x Framebuffer support"
+ depends on FB && (ARCH_DAVINCI_DA8XX || SOC_AM33XX)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_CFB_REV_PIXELS_IN_BYTE
+ select FB_MODE_HELPERS
+ select VIDEOMODE_HELPERS
+ ---help---
+ This is the frame buffer device driver for the TI LCD controller
+ found on DA8xx/OMAP-L1xx/AM335x SoCs.
+ If unsure, say N.
+
+config FB_VIRTUAL
+ tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
+ depends on FB
+ select FB_SYS_FILLRECT
+ select FB_SYS_COPYAREA
+ select FB_SYS_IMAGEBLIT
+ select FB_SYS_FOPS
+ ---help---
+ This is a `virtual' frame buffer device. It operates on a chunk of
+ unswappable kernel memory instead of on the memory of a graphics
+ board. This means you cannot see any output sent to this frame
+ buffer device, while it does consume precious memory. The main use
+ of this frame buffer device is testing and debugging the frame
+ buffer subsystem. Do NOT enable it for normal systems! To protect
+ the innocent, it has to be enabled explicitly at boot time using the
+ kernel option `video=vfb:'.
+
+ To compile this driver as a module, choose M here: the
+ module will be called vfb. In order to load it, you must use
+ the vfb_enable=1 option.
+
+ If unsure, say N.
+
+config XEN_FBDEV_FRONTEND
+ tristate "Xen virtual frame buffer support"
+ depends on FB && XEN
+ select FB_SYS_FILLRECT
+ select FB_SYS_COPYAREA
+ select FB_SYS_IMAGEBLIT
+ select FB_SYS_FOPS
+ select FB_DEFERRED_IO
+ select INPUT_XEN_KBDDEV_FRONTEND if INPUT_MISC
+ select XEN_XENBUS_FRONTEND
+ default y
+ help
+ This driver implements the front-end of the Xen virtual
+ frame buffer driver. It communicates with a back-end
+ in another domain.
+
+config FB_METRONOME
+ tristate "E-Ink Metronome/8track controller support"
+ depends on FB
+ select FB_SYS_FILLRECT
+ select FB_SYS_COPYAREA
+ select FB_SYS_IMAGEBLIT
+ select FB_SYS_FOPS
+ select FB_DEFERRED_IO
+ help
+ This driver implements support for the E-Ink Metronome
+ controller. The pre-release name for this device was 8track
+ and could also have been called by some vendors as PVI-nnnn.
+
+config FB_MB862XX
+ tristate "Fujitsu MB862xx GDC support"
+ depends on FB
+ depends on PCI || (OF && PPC)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ ---help---
+ Frame buffer driver for Fujitsu Carmine/Coral-P(A)/Lime controllers.
+
+choice
+ prompt "GDC variant"
+ depends on FB_MB862XX
+
+config FB_MB862XX_PCI_GDC
+ bool "Carmine/Coral-P(A) GDC"
+ depends on PCI
+ ---help---
+ This enables framebuffer support for Fujitsu Carmine/Coral-P(A)
+ PCI graphics controller devices.
+
+config FB_MB862XX_LIME
+ bool "Lime GDC"
+ depends on OF && PPC
+ select FB_FOREIGN_ENDIAN
+ select FB_LITTLE_ENDIAN
+ ---help---
+ Framebuffer support for Fujitsu Lime GDC on host CPU bus.
+
+endchoice
+
+config FB_MB862XX_I2C
+ bool "Support I2C bus on MB862XX GDC"
+ depends on FB_MB862XX && I2C
+ default y
+ help
+ Selecting this option adds Coral-P(A)/Lime GDC I2C bus adapter
+ driver to support accessing I2C devices on controller's I2C bus.
+ These are usually some video decoder chips.
+
+config FB_EP93XX
+ tristate "EP93XX frame buffer support"
+ depends on FB && ARCH_EP93XX
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ ---help---
+ Framebuffer driver for the Cirrus Logic EP93XX series of processors.
+ This driver is also available as a module. The module will be called
+ ep93xx-fb.
+
+config FB_PRE_INIT_FB
+ bool "Don't reinitialize, use bootloader's GDC/Display configuration"
+ depends on FB && FB_MB862XX_LIME
+ ---help---
+ Select this option if display contents should be inherited as set by
+ the bootloader.
+
+config FB_MSM
+ tristate "MSM Framebuffer support"
+ depends on FB && ARCH_MSM
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+
+config FB_MX3
+ tristate "MX3 Framebuffer support"
+ depends on FB && MX3_IPU
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ default y
+ help
+ This is a framebuffer device for the i.MX31 LCD Controller. So
+ far only synchronous displays are supported. If you plan to use
+ an LCD display with your i.MX31 system, say Y here.
+
+config FB_BROADSHEET
+ tristate "E-Ink Broadsheet/Epson S1D13521 controller support"
+ depends on FB
+ select FB_SYS_FILLRECT
+ select FB_SYS_COPYAREA
+ select FB_SYS_IMAGEBLIT
+ select FB_SYS_FOPS
+ select FB_DEFERRED_IO
+ help
+ This driver implements support for the E-Ink Broadsheet
+ controller. The release name for this device was Epson S1D13521
+ and could also have been called by other names when coupled with
+ a bridge adapter.
+
+config FB_AUO_K190X
+ tristate "AUO-K190X EPD controller support"
+ depends on FB
+ select FB_SYS_FILLRECT
+ select FB_SYS_COPYAREA
+ select FB_SYS_IMAGEBLIT
+ select FB_SYS_FOPS
+ select FB_DEFERRED_IO
+ help
+ Provides support for epaper controllers from the K190X series
+ of AUO. These controllers can be used to drive epaper displays
+ from Sipix.
+
+ This option enables the common support, shared by the individual
+ controller drivers. You will also have to enable the driver
+ for the controller type used in your device.
+
+config FB_AUO_K1900
+ tristate "AUO-K1900 EPD controller support"
+ depends on FB && FB_AUO_K190X
+ help
+ This driver implements support for the AUO K1900 epd-controller.
+ This controller can drive Sipix epaper displays but can only do
+ serial updates, reducing the number of possible frames per second.
+
+config FB_AUO_K1901
+ tristate "AUO-K1901 EPD controller support"
+ depends on FB && FB_AUO_K190X
+ help
+ This driver implements support for the AUO K1901 epd-controller.
+ This controller can drive Sipix epaper displays and supports
+ concurrent updates, making higher frames per second possible.
+
+config FB_JZ4740
+ tristate "JZ4740 LCD framebuffer support"
+ depends on FB && MACH_JZ4740
+ select FB_SYS_FILLRECT
+ select FB_SYS_COPYAREA
+ select FB_SYS_IMAGEBLIT
+ help
+ Framebuffer support for the JZ4740 SoC.
+
+config FB_MXS
+ tristate "MXS LCD framebuffer support"
+ depends on FB && ARCH_MXS
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_MODE_HELPERS
+ select VIDEOMODE_HELPERS
+ help
+ Framebuffer support for the MXS SoC.
+
+config FB_PUV3_UNIGFX
+ tristate "PKUnity v3 Unigfx framebuffer support"
+ depends on FB && UNICORE32 && ARCH_PUV3
+ select FB_SYS_FILLRECT
+ select FB_SYS_COPYAREA
+ select FB_SYS_IMAGEBLIT
+ select FB_SYS_FOPS
+ help
+ Choose this option if you want to use the Unigfx device as a
+ framebuffer device. Without the support of PCI & AGP.
+
+config FB_HYPERV
+ tristate "Microsoft Hyper-V Synthetic Video support"
+ depends on FB && HYPERV
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This framebuffer driver supports Microsoft Hyper-V Synthetic Video.
+
+config FB_SIMPLE
+ bool "Simple framebuffer support"
+ depends on (FB = y)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ Say Y if you want support for a simple frame-buffer.
+
+ This driver assumes that the display hardware has been initialized
+ before the kernel boots, and the kernel will simply render to the
+ pre-allocated frame buffer surface.
+
+ Configuration re: surface address, size, and format must be provided
+ through device tree, or plain old platform data.
+
+source "drivers/video/fbdev/omap/Kconfig"
+source "drivers/video/fbdev/omap2/Kconfig"
+source "drivers/video/fbdev/exynos/Kconfig"
+source "drivers/video/fbdev/mmp/Kconfig"
+
+config FB_SH_MOBILE_MERAM
+ tristate "SuperH Mobile MERAM read ahead support"
+ depends on (SUPERH || ARCH_SHMOBILE)
+ select GENERIC_ALLOCATOR
+ ---help---
+ Enable MERAM support for the SuperH controller.
+
+ This will allow for caching of the framebuffer to provide more
+ reliable access under heavy main memory bus traffic situations.
+ Up to 4 memory channels can be configured, allowing 4 RGB or
+ 2 YCbCr framebuffers to be configured.
+
+config FB_SSD1307
+ tristate "Solomon SSD1307 framebuffer support"
+ depends on FB && I2C
+ depends on OF
+ depends on GPIOLIB
+ select FB_SYS_FOPS
+ select FB_SYS_FILLRECT
+ select FB_SYS_COPYAREA
+ select FB_SYS_IMAGEBLIT
+ select FB_DEFERRED_IO
+ select PWM
+ help
+ This driver implements support for the Solomon SSD1307
+ OLED controller over I2C.
diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile
new file mode 100644
index 000000000000..0284f2a12538
--- /dev/null
+++ b/drivers/video/fbdev/Makefile
@@ -0,0 +1,152 @@
+# Makefile for the Linux video drivers.
+# 5 Aug 1999, James Simmons, <mailto:jsimmons@users.sf.net>
+# Rewritten to use lists instead of if-statements.
+
+# Each configuration option enables a list of files.
+
+obj-y += core/
+
+obj-$(CONFIG_EXYNOS_VIDEO) += exynos/
+
+obj-$(CONFIG_FB_MACMODES) += macmodes.o
+obj-$(CONFIG_FB_WMT_GE_ROPS) += wmt_ge_rops.o
+
+# Hardware specific drivers go first
+obj-$(CONFIG_FB_AMIGA) += amifb.o c2p_planar.o
+obj-$(CONFIG_FB_ARC) += arcfb.o
+obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o
+obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o
+obj-$(CONFIG_FB_GRVGA) += grvga.o
+obj-$(CONFIG_FB_PM2) += pm2fb.o
+obj-$(CONFIG_FB_PM3) += pm3fb.o
+
+obj-$(CONFIG_FB_I740) += i740fb.o
+obj-$(CONFIG_FB_MATROX) += matrox/
+obj-$(CONFIG_FB_RIVA) += riva/
+obj-$(CONFIG_FB_NVIDIA) += nvidia/
+obj-$(CONFIG_FB_ATY) += aty/ macmodes.o
+obj-$(CONFIG_FB_ATY128) += aty/ macmodes.o
+obj-$(CONFIG_FB_RADEON) += aty/
+obj-$(CONFIG_FB_SIS) += sis/
+obj-$(CONFIG_FB_VIA) += via/
+obj-$(CONFIG_FB_KYRO) += kyro/
+obj-$(CONFIG_FB_SAVAGE) += savage/
+obj-$(CONFIG_FB_GEODE) += geode/
+obj-$(CONFIG_FB_MBX) += mbx/
+obj-$(CONFIG_FB_NEOMAGIC) += neofb.o
+obj-$(CONFIG_FB_3DFX) += tdfxfb.o
+obj-$(CONFIG_FB_CONTROL) += controlfb.o
+obj-$(CONFIG_FB_PLATINUM) += platinumfb.o
+obj-$(CONFIG_FB_VALKYRIE) += valkyriefb.o
+obj-$(CONFIG_FB_CT65550) += chipsfb.o
+obj-$(CONFIG_FB_IMSTT) += imsttfb.o
+obj-$(CONFIG_FB_FM2) += fm2fb.o
+obj-$(CONFIG_FB_VT8623) += vt8623fb.o
+obj-$(CONFIG_FB_TRIDENT) += tridentfb.o
+obj-$(CONFIG_FB_LE80578) += vermilion/
+obj-$(CONFIG_FB_S3) += s3fb.o
+obj-$(CONFIG_FB_ARK) += arkfb.o
+obj-$(CONFIG_FB_STI) += stifb.o
+obj-$(CONFIG_FB_FFB) += ffb.o sbuslib.o
+obj-$(CONFIG_FB_CG6) += cg6.o sbuslib.o
+obj-$(CONFIG_FB_CG3) += cg3.o sbuslib.o
+obj-$(CONFIG_FB_BW2) += bw2.o sbuslib.o
+obj-$(CONFIG_FB_CG14) += cg14.o sbuslib.o
+obj-$(CONFIG_FB_P9100) += p9100.o sbuslib.o
+obj-$(CONFIG_FB_TCX) += tcx.o sbuslib.o
+obj-$(CONFIG_FB_LEO) += leo.o sbuslib.o
+obj-$(CONFIG_FB_ACORN) += acornfb.o
+obj-$(CONFIG_FB_ATARI) += atafb.o c2p_iplan2.o atafb_mfb.o \
+ atafb_iplan2p2.o atafb_iplan2p4.o atafb_iplan2p8.o
+obj-$(CONFIG_FB_MAC) += macfb.o
+obj-$(CONFIG_FB_HECUBA) += hecubafb.o
+obj-$(CONFIG_FB_N411) += n411.o
+obj-$(CONFIG_FB_HGA) += hgafb.o
+obj-$(CONFIG_FB_XVR500) += sunxvr500.o
+obj-$(CONFIG_FB_XVR2500) += sunxvr2500.o
+obj-$(CONFIG_FB_XVR1000) += sunxvr1000.o
+obj-$(CONFIG_FB_IGA) += igafb.o
+obj-$(CONFIG_FB_APOLLO) += dnfb.o
+obj-$(CONFIG_FB_Q40) += q40fb.o
+obj-$(CONFIG_FB_TGA) += tgafb.o
+obj-$(CONFIG_FB_HP300) += hpfb.o
+obj-$(CONFIG_FB_G364) += g364fb.o
+obj-$(CONFIG_FB_EP93XX) += ep93xx-fb.o
+obj-$(CONFIG_FB_SA1100) += sa1100fb.o
+obj-$(CONFIG_FB_HIT) += hitfb.o
+obj-$(CONFIG_FB_ATMEL) += atmel_lcdfb.o
+obj-$(CONFIG_FB_PVR2) += pvr2fb.o
+obj-$(CONFIG_FB_VOODOO1) += sstfb.o
+obj-$(CONFIG_FB_ARMCLCD) += amba-clcd.o
+obj-$(CONFIG_FB_GOLDFISH) += goldfishfb.o
+obj-$(CONFIG_FB_68328) += 68328fb.o
+obj-$(CONFIG_FB_GBE) += gbefb.o
+obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o
+obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o
+obj-$(CONFIG_FB_PXA) += pxafb.o
+obj-$(CONFIG_FB_PXA168) += pxa168fb.o
+obj-$(CONFIG_PXA3XX_GCU) += pxa3xx-gcu.o
+obj-$(CONFIG_MMP_DISP) += mmp/
+obj-$(CONFIG_FB_W100) += w100fb.o
+obj-$(CONFIG_FB_TMIO) += tmiofb.o
+obj-$(CONFIG_FB_AU1100) += au1100fb.o
+obj-$(CONFIG_FB_AU1200) += au1200fb.o
+obj-$(CONFIG_FB_VT8500) += vt8500lcdfb.o
+obj-$(CONFIG_FB_WM8505) += wm8505fb.o
+obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.o
+obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o
+obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o
+obj-$(CONFIG_FB_MAXINE) += maxinefb.o
+obj-$(CONFIG_FB_METRONOME) += metronomefb.o
+obj-$(CONFIG_FB_BROADSHEET) += broadsheetfb.o
+obj-$(CONFIG_FB_AUO_K190X) += auo_k190x.o
+obj-$(CONFIG_FB_AUO_K1900) += auo_k1900fb.o
+obj-$(CONFIG_FB_AUO_K1901) += auo_k1901fb.o
+obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o
+obj-$(CONFIG_FB_SH7760) += sh7760fb.o
+obj-$(CONFIG_FB_IMX) += imxfb.o
+obj-$(CONFIG_FB_S3C) += s3c-fb.o
+obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o
+obj-$(CONFIG_FB_FSL_DIU) += fsl-diu-fb.o
+obj-$(CONFIG_FB_COBALT) += cobalt_lcdfb.o
+obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o
+obj-$(CONFIG_FB_PS3) += ps3fb.o
+obj-$(CONFIG_FB_SM501) += sm501fb.o
+obj-$(CONFIG_FB_UDL) += udlfb.o
+obj-$(CONFIG_FB_SMSCUFX) += smscufx.o
+obj-$(CONFIG_FB_XILINX) += xilinxfb.o
+obj-$(CONFIG_SH_MIPI_DSI) += sh_mipi_dsi.o
+obj-$(CONFIG_FB_SH_MOBILE_HDMI) += sh_mobile_hdmi.o
+obj-$(CONFIG_FB_SH_MOBILE_MERAM) += sh_mobile_meram.o
+obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o
+obj-$(CONFIG_FB_OMAP) += omap/
+obj-y += omap2/
+obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o
+obj-$(CONFIG_FB_CARMINE) += carminefb.o
+obj-$(CONFIG_FB_MB862XX) += mb862xx/
+obj-$(CONFIG_FB_MSM) += msm/
+obj-$(CONFIG_FB_NUC900) += nuc900fb.o
+obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o
+obj-$(CONFIG_FB_PUV3_UNIGFX) += fb-puv3.o
+obj-$(CONFIG_FB_HYPERV) += hyperv_fb.o
+obj-$(CONFIG_FB_OPENCORES) += ocfb.o
+
+# Platform or fallback drivers go here
+obj-$(CONFIG_FB_UVESA) += uvesafb.o
+obj-$(CONFIG_FB_VESA) += vesafb.o
+obj-$(CONFIG_FB_EFI) += efifb.o
+obj-$(CONFIG_FB_VGA16) += vga16fb.o
+obj-$(CONFIG_FB_OF) += offb.o
+obj-$(CONFIG_FB_BF537_LQ035) += bf537-lq035.o
+obj-$(CONFIG_FB_BF54X_LQ043) += bf54x-lq043fb.o
+obj-$(CONFIG_FB_BFIN_LQ035Q1) += bfin-lq035q1-fb.o
+obj-$(CONFIG_FB_BFIN_T350MCQB) += bfin-t350mcqb-fb.o
+obj-$(CONFIG_FB_BFIN_7393) += bfin_adv7393fb.o
+obj-$(CONFIG_FB_MX3) += mx3fb.o
+obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o
+obj-$(CONFIG_FB_MXS) += mxsfb.o
+obj-$(CONFIG_FB_SSD1307) += ssd1307fb.o
+obj-$(CONFIG_FB_SIMPLE) += simplefb.o
+
+# the test framebuffer is last
+obj-$(CONFIG_FB_VIRTUAL) += vfb.o
diff --git a/drivers/video/acornfb.c b/drivers/video/fbdev/acornfb.c
index a305caea58ee..a305caea58ee 100644
--- a/drivers/video/acornfb.c
+++ b/drivers/video/fbdev/acornfb.c
diff --git a/drivers/video/acornfb.h b/drivers/video/fbdev/acornfb.h
index 175c8ff3367c..175c8ff3367c 100644
--- a/drivers/video/acornfb.h
+++ b/drivers/video/fbdev/acornfb.h
diff --git a/drivers/video/amba-clcd.c b/drivers/video/fbdev/amba-clcd.c
index 14d6b3793e0a..14d6b3793e0a 100644
--- a/drivers/video/amba-clcd.c
+++ b/drivers/video/fbdev/amba-clcd.c
diff --git a/drivers/video/amifb.c b/drivers/video/fbdev/amifb.c
index 518f790ef88a..518f790ef88a 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/fbdev/amifb.c
diff --git a/drivers/video/arcfb.c b/drivers/video/fbdev/arcfb.c
index 1b0b233b8b39..1b0b233b8b39 100644
--- a/drivers/video/arcfb.c
+++ b/drivers/video/fbdev/arcfb.c
diff --git a/drivers/video/arkfb.c b/drivers/video/fbdev/arkfb.c
index adc4ea2cc5a0..adc4ea2cc5a0 100644
--- a/drivers/video/arkfb.c
+++ b/drivers/video/fbdev/arkfb.c
diff --git a/drivers/video/asiliantfb.c b/drivers/video/fbdev/asiliantfb.c
index 7e8ddf00ccc2..7e8ddf00ccc2 100644
--- a/drivers/video/asiliantfb.c
+++ b/drivers/video/fbdev/asiliantfb.c
diff --git a/drivers/video/atafb.c b/drivers/video/fbdev/atafb.c
index e21d1f58554c..4953b657635e 100644
--- a/drivers/video/atafb.c
+++ b/drivers/video/fbdev/atafb.c
@@ -191,7 +191,7 @@ static struct fb_info fb_info = {
};
static void *screen_base; /* base address of screen */
-static void *real_screen_base; /* (only for Overscan) */
+static unsigned long phys_screen_base; /* (only for Overscan) */
static int screen_len;
@@ -213,7 +213,8 @@ static unsigned int external_yres;
*/
static unsigned int external_depth;
static int external_pmode;
-static void *external_addr;
+static void *external_screen_base;
+static unsigned long external_addr;
static unsigned long external_len;
static unsigned long external_vgaiobase;
static unsigned int external_bitspercol = 6;
@@ -592,7 +593,7 @@ static int tt_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
int mode;
strcpy(fix->id, "Atari Builtin");
- fix->smem_start = (unsigned long)real_screen_base;
+ fix->smem_start = phys_screen_base;
fix->smem_len = screen_len;
fix->type = FB_TYPE_INTERLEAVED_PLANES;
fix->type_aux = 2;
@@ -790,7 +791,7 @@ static void tt_get_par(struct atafb_par *par)
addr = ((shifter.bas_hi & 0xff) << 16) |
((shifter.bas_md & 0xff) << 8) |
((shifter.bas_lo & 0xff));
- par->screen_base = phys_to_virt(addr);
+ par->screen_base = atari_stram_to_virt(addr);
}
static void tt_set_par(struct atafb_par *par)
@@ -888,7 +889,7 @@ static int falcon_encode_fix(struct fb_fix_screeninfo *fix,
struct atafb_par *par)
{
strcpy(fix->id, "Atari Builtin");
- fix->smem_start = (unsigned long)real_screen_base;
+ fix->smem_start = phys_screen_base;
fix->smem_len = screen_len;
fix->type = FB_TYPE_INTERLEAVED_PLANES;
fix->type_aux = 2;
@@ -1584,7 +1585,7 @@ static void falcon_get_par(struct atafb_par *par)
addr = (shifter.bas_hi & 0xff) << 16 |
(shifter.bas_md & 0xff) << 8 |
(shifter.bas_lo & 0xff);
- par->screen_base = phys_to_virt(addr);
+ par->screen_base = atari_stram_to_virt(addr);
/* derived parameters */
hw->ste_mode = (hw->f_shift & 0x510) == 0 && hw->st_shift == 0x100;
@@ -1814,7 +1815,7 @@ static int stste_encode_fix(struct fb_fix_screeninfo *fix,
int mode;
strcpy(fix->id, "Atari Builtin");
- fix->smem_start = (unsigned long)real_screen_base;
+ fix->smem_start = phys_screen_base;
fix->smem_len = screen_len;
fix->type = FB_TYPE_INTERLEAVED_PLANES;
fix->type_aux = 2;
@@ -1980,7 +1981,7 @@ static void stste_get_par(struct atafb_par *par)
((shifter.bas_md & 0xff) << 8);
if (ATARIHW_PRESENT(EXTD_SHIFTER))
addr |= (shifter.bas_lo & 0xff);
- par->screen_base = phys_to_virt(addr);
+ par->screen_base = atari_stram_to_virt(addr);
}
static void stste_set_par(struct atafb_par *par)
@@ -2039,7 +2040,7 @@ static int stste_detect(void)
static void stste_set_screen_base(void *s_base)
{
unsigned long addr;
- addr = virt_to_phys(s_base);
+ addr = atari_stram_to_phys(s_base);
/* Setup Screen Memory */
shifter.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
shifter.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
@@ -2113,7 +2114,7 @@ static void st_ovsc_switch(void)
static int ext_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
{
strcpy(fix->id, "Unknown Extern");
- fix->smem_start = (unsigned long)external_addr;
+ fix->smem_start = external_addr;
fix->smem_len = PAGE_ALIGN(external_len);
if (external_depth == 1) {
fix->type = FB_TYPE_PACKED_PIXELS;
@@ -2213,7 +2214,7 @@ static int ext_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
static void ext_get_par(struct atafb_par *par)
{
- par->screen_base = external_addr;
+ par->screen_base = external_screen_base;
}
static void ext_set_par(struct atafb_par *par)
@@ -2286,7 +2287,7 @@ static void set_screen_base(void *s_base)
{
unsigned long addr;
- addr = virt_to_phys(s_base);
+ addr = atari_stram_to_phys(s_base);
/* Setup Screen Memory */
shifter.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
shifter.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
@@ -2433,7 +2434,9 @@ static void atafb_set_disp(struct fb_info *info)
atafb_get_var(&info->var, info);
atafb_get_fix(&info->fix, info);
- info->screen_base = (void *)info->fix.smem_start;
+ /* Note: smem_start derives from phys_screen_base, not screen_base! */
+ info->screen_base = (external_addr ? external_screen_base :
+ atari_stram_to_virt(info->fix.smem_start));
}
static int atafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
@@ -2904,7 +2907,7 @@ static void __init atafb_setup_ext(char *spec)
external_yres = yres;
external_depth = depth;
external_pmode = planes;
- external_addr = (void *)addr;
+ external_addr = addr;
external_len = len;
if (external_card_type == IS_MV300) {
@@ -3166,30 +3169,30 @@ int __init atafb_init(void)
memset(screen_base, 0, mem_req);
pad = -(unsigned long)screen_base & (PAGE_SIZE - 1);
screen_base += pad;
- real_screen_base = screen_base + ovsc_offset;
+ phys_screen_base = atari_stram_to_phys(screen_base + ovsc_offset);
screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK;
st_ovsc_switch();
if (CPU_IS_040_OR_060) {
/* On a '040+, the cache mode of video RAM must be set to
* write-through also for internal video hardware! */
- cache_push(virt_to_phys(screen_base), screen_len);
+ cache_push(atari_stram_to_phys(screen_base), screen_len);
kernel_set_cachemode(screen_base, screen_len,
IOMAP_WRITETHROUGH);
}
- printk("atafb: screen_base %p real_screen_base %p screen_len %d\n",
- screen_base, real_screen_base, screen_len);
+ printk("atafb: screen_base %p phys_screen_base %lx screen_len %d\n",
+ screen_base, phys_screen_base, screen_len);
#ifdef ATAFB_EXT
} else {
/* Map the video memory (physical address given) to somewhere
* in the kernel address space.
*/
- external_addr = ioremap_writethrough((unsigned long)external_addr,
+ external_screen_base = ioremap_writethrough(external_addr,
external_len);
if (external_vgaiobase)
external_vgaiobase =
(unsigned long)ioremap(external_vgaiobase, 0x10000);
- screen_base =
- real_screen_base = external_addr;
+ screen_base = external_screen_base;
+ phys_screen_base = external_addr;
screen_len = external_len & PAGE_MASK;
memset (screen_base, 0, external_len);
}
@@ -3235,8 +3238,8 @@ int __init atafb_init(void)
if (register_framebuffer(&fb_info) < 0) {
#ifdef ATAFB_EXT
if (external_addr) {
- iounmap(external_addr);
- external_addr = NULL;
+ iounmap(external_screen_base);
+ external_addr = 0;
}
if (external_vgaiobase) {
iounmap((void*)external_vgaiobase);
diff --git a/drivers/video/atafb.h b/drivers/video/fbdev/atafb.h
index 014e05906cb1..014e05906cb1 100644
--- a/drivers/video/atafb.h
+++ b/drivers/video/fbdev/atafb.h
diff --git a/drivers/video/atafb_iplan2p2.c b/drivers/video/fbdev/atafb_iplan2p2.c
index 8cc9c50379d0..8cc9c50379d0 100644
--- a/drivers/video/atafb_iplan2p2.c
+++ b/drivers/video/fbdev/atafb_iplan2p2.c
diff --git a/drivers/video/atafb_iplan2p4.c b/drivers/video/fbdev/atafb_iplan2p4.c
index bee0d89463f7..bee0d89463f7 100644
--- a/drivers/video/atafb_iplan2p4.c
+++ b/drivers/video/fbdev/atafb_iplan2p4.c
diff --git a/drivers/video/atafb_iplan2p8.c b/drivers/video/fbdev/atafb_iplan2p8.c
index 356fb52ce443..356fb52ce443 100644
--- a/drivers/video/atafb_iplan2p8.c
+++ b/drivers/video/fbdev/atafb_iplan2p8.c
diff --git a/drivers/video/atafb_mfb.c b/drivers/video/fbdev/atafb_mfb.c
index 6a352d62eecf..6a352d62eecf 100644
--- a/drivers/video/atafb_mfb.c
+++ b/drivers/video/fbdev/atafb_mfb.c
diff --git a/drivers/video/atafb_utils.h b/drivers/video/fbdev/atafb_utils.h
index ac9e19dc5057..ac9e19dc5057 100644
--- a/drivers/video/atafb_utils.h
+++ b/drivers/video/fbdev/atafb_utils.h
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/fbdev/atmel_lcdfb.c
index e683b6ef9594..e683b6ef9594 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/fbdev/atmel_lcdfb.c
diff --git a/drivers/video/aty/Makefile b/drivers/video/fbdev/aty/Makefile
index a6cc0e9ec790..a6cc0e9ec790 100644
--- a/drivers/video/aty/Makefile
+++ b/drivers/video/fbdev/aty/Makefile
diff --git a/drivers/video/aty/ati_ids.h b/drivers/video/fbdev/aty/ati_ids.h
index 3e9d28bcd9f8..3e9d28bcd9f8 100644
--- a/drivers/video/aty/ati_ids.h
+++ b/drivers/video/fbdev/aty/ati_ids.h
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/fbdev/aty/aty128fb.c
index 52108be69e77..52108be69e77 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/fbdev/aty/aty128fb.c
diff --git a/drivers/video/aty/atyfb.h b/drivers/video/fbdev/aty/atyfb.h
index 1f39a62f899b..1f39a62f899b 100644
--- a/drivers/video/aty/atyfb.h
+++ b/drivers/video/fbdev/aty/atyfb.h
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/fbdev/aty/atyfb_base.c
index c3d0074a32db..c3d0074a32db 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/fbdev/aty/atyfb_base.c
diff --git a/drivers/video/aty/mach64_accel.c b/drivers/video/fbdev/aty/mach64_accel.c
index 182bd680141f..182bd680141f 100644
--- a/drivers/video/aty/mach64_accel.c
+++ b/drivers/video/fbdev/aty/mach64_accel.c
diff --git a/drivers/video/aty/mach64_ct.c b/drivers/video/fbdev/aty/mach64_ct.c
index 51f29d627ceb..51f29d627ceb 100644
--- a/drivers/video/aty/mach64_ct.c
+++ b/drivers/video/fbdev/aty/mach64_ct.c
diff --git a/drivers/video/aty/mach64_cursor.c b/drivers/video/fbdev/aty/mach64_cursor.c
index 0fe02e22d9a4..2fa0317ab3c7 100644
--- a/drivers/video/aty/mach64_cursor.c
+++ b/drivers/video/fbdev/aty/mach64_cursor.c
@@ -5,7 +5,7 @@
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/string.h>
-#include "../fb_draw.h"
+#include "../core/fb_draw.h"
#include <asm/io.h>
diff --git a/drivers/video/aty/mach64_gx.c b/drivers/video/fbdev/aty/mach64_gx.c
index 10c988aef58e..10c988aef58e 100644
--- a/drivers/video/aty/mach64_gx.c
+++ b/drivers/video/fbdev/aty/mach64_gx.c
diff --git a/drivers/video/aty/radeon_accel.c b/drivers/video/fbdev/aty/radeon_accel.c
index a469a3d6edcb..a469a3d6edcb 100644
--- a/drivers/video/aty/radeon_accel.c
+++ b/drivers/video/fbdev/aty/radeon_accel.c
diff --git a/drivers/video/aty/radeon_backlight.c b/drivers/video/fbdev/aty/radeon_backlight.c
index db572df7e1ef..db572df7e1ef 100644
--- a/drivers/video/aty/radeon_backlight.c
+++ b/drivers/video/fbdev/aty/radeon_backlight.c
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/fbdev/aty/radeon_base.c
index 26d80a4486fb..26d80a4486fb 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/fbdev/aty/radeon_base.c
diff --git a/drivers/video/aty/radeon_i2c.c b/drivers/video/fbdev/aty/radeon_i2c.c
index ab1d0fd76316..ab1d0fd76316 100644
--- a/drivers/video/aty/radeon_i2c.c
+++ b/drivers/video/fbdev/aty/radeon_i2c.c
diff --git a/drivers/video/aty/radeon_monitor.c b/drivers/video/fbdev/aty/radeon_monitor.c
index bc078d50d8f1..bc078d50d8f1 100644
--- a/drivers/video/aty/radeon_monitor.c
+++ b/drivers/video/fbdev/aty/radeon_monitor.c
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/fbdev/aty/radeon_pm.c
index 46a12f1a93c3..46a12f1a93c3 100644
--- a/drivers/video/aty/radeon_pm.c
+++ b/drivers/video/fbdev/aty/radeon_pm.c
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/fbdev/aty/radeonfb.h
index cb846044f57c..cb846044f57c 100644
--- a/drivers/video/aty/radeonfb.h
+++ b/drivers/video/fbdev/aty/radeonfb.h
diff --git a/drivers/video/au1100fb.c b/drivers/video/fbdev/au1100fb.c
index 372d4aea9d1c..372d4aea9d1c 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/fbdev/au1100fb.c
diff --git a/drivers/video/au1100fb.h b/drivers/video/fbdev/au1100fb.h
index 12d9642d5465..12d9642d5465 100644
--- a/drivers/video/au1100fb.h
+++ b/drivers/video/fbdev/au1100fb.h
diff --git a/drivers/video/au1200fb.c b/drivers/video/fbdev/au1200fb.c
index 4cfba78a1458..4cfba78a1458 100644
--- a/drivers/video/au1200fb.c
+++ b/drivers/video/fbdev/au1200fb.c
diff --git a/drivers/video/au1200fb.h b/drivers/video/fbdev/au1200fb.h
index e2672714d8d4..e2672714d8d4 100644
--- a/drivers/video/au1200fb.h
+++ b/drivers/video/fbdev/au1200fb.h
diff --git a/drivers/video/auo_k1900fb.c b/drivers/video/fbdev/auo_k1900fb.c
index f5b668e77af3..f5b668e77af3 100644
--- a/drivers/video/auo_k1900fb.c
+++ b/drivers/video/fbdev/auo_k1900fb.c
diff --git a/drivers/video/auo_k1901fb.c b/drivers/video/fbdev/auo_k1901fb.c
index 12b9adcb75c5..12b9adcb75c5 100644
--- a/drivers/video/auo_k1901fb.c
+++ b/drivers/video/fbdev/auo_k1901fb.c
diff --git a/drivers/video/auo_k190x.c b/drivers/video/fbdev/auo_k190x.c
index 8d2499d1cafb..8d2499d1cafb 100644
--- a/drivers/video/auo_k190x.c
+++ b/drivers/video/fbdev/auo_k190x.c
diff --git a/drivers/video/auo_k190x.h b/drivers/video/fbdev/auo_k190x.h
index e35af1f51b28..e35af1f51b28 100644
--- a/drivers/video/auo_k190x.h
+++ b/drivers/video/fbdev/auo_k190x.h
diff --git a/drivers/video/bf537-lq035.c b/drivers/video/fbdev/bf537-lq035.c
index a82d2578d976..a82d2578d976 100644
--- a/drivers/video/bf537-lq035.c
+++ b/drivers/video/fbdev/bf537-lq035.c
diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/fbdev/bf54x-lq043fb.c
index 42b8f9d11018..e2c42ad8515a 100644
--- a/drivers/video/bf54x-lq043fb.c
+++ b/drivers/video/fbdev/bf54x-lq043fb.c
@@ -49,13 +49,13 @@
#include <linux/spinlock.h>
#include <linux/dma-mapping.h>
#include <linux/platform_device.h>
+#include <linux/gpio.h>
#include <asm/blackfin.h>
#include <asm/irq.h>
#include <asm/dpmc.h>
#include <asm/dma-mapping.h>
#include <asm/dma.h>
-#include <asm/gpio.h>
#include <asm/portmux.h>
#include <mach/bf54x-lq043.h>
diff --git a/drivers/video/bfin-lq035q1-fb.c b/drivers/video/fbdev/bfin-lq035q1-fb.c
index b594a58ff21d..b594a58ff21d 100644
--- a/drivers/video/bfin-lq035q1-fb.c
+++ b/drivers/video/fbdev/bfin-lq035q1-fb.c
diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/fbdev/bfin-t350mcqb-fb.c
index b5cf1307a3d9..b5cf1307a3d9 100644
--- a/drivers/video/bfin-t350mcqb-fb.c
+++ b/drivers/video/fbdev/bfin-t350mcqb-fb.c
diff --git a/drivers/video/bfin_adv7393fb.c b/drivers/video/fbdev/bfin_adv7393fb.c
index a54f7f7d763b..a54f7f7d763b 100644
--- a/drivers/video/bfin_adv7393fb.c
+++ b/drivers/video/fbdev/bfin_adv7393fb.c
diff --git a/drivers/video/bfin_adv7393fb.h b/drivers/video/fbdev/bfin_adv7393fb.h
index cd591b5152a5..cd591b5152a5 100644
--- a/drivers/video/bfin_adv7393fb.h
+++ b/drivers/video/fbdev/bfin_adv7393fb.h
diff --git a/drivers/video/broadsheetfb.c b/drivers/video/fbdev/broadsheetfb.c
index 8556264b16b7..8556264b16b7 100644
--- a/drivers/video/broadsheetfb.c
+++ b/drivers/video/fbdev/broadsheetfb.c
diff --git a/drivers/video/bt431.h b/drivers/video/fbdev/bt431.h
index 04e0cfbba538..04e0cfbba538 100644
--- a/drivers/video/bt431.h
+++ b/drivers/video/fbdev/bt431.h
diff --git a/drivers/video/bt455.h b/drivers/video/fbdev/bt455.h
index 80f61b03e9ae..80f61b03e9ae 100644
--- a/drivers/video/bt455.h
+++ b/drivers/video/fbdev/bt455.h
diff --git a/drivers/video/bw2.c b/drivers/video/fbdev/bw2.c
index bc123d6947a4..bc123d6947a4 100644
--- a/drivers/video/bw2.c
+++ b/drivers/video/fbdev/bw2.c
diff --git a/drivers/video/c2p.h b/drivers/video/fbdev/c2p.h
index 6c38d40427d8..6c38d40427d8 100644
--- a/drivers/video/c2p.h
+++ b/drivers/video/fbdev/c2p.h
diff --git a/drivers/video/c2p_core.h b/drivers/video/fbdev/c2p_core.h
index e1035a865fb9..e1035a865fb9 100644
--- a/drivers/video/c2p_core.h
+++ b/drivers/video/fbdev/c2p_core.h
diff --git a/drivers/video/c2p_iplan2.c b/drivers/video/fbdev/c2p_iplan2.c
index 19156dc6158c..19156dc6158c 100644
--- a/drivers/video/c2p_iplan2.c
+++ b/drivers/video/fbdev/c2p_iplan2.c
diff --git a/drivers/video/c2p_planar.c b/drivers/video/fbdev/c2p_planar.c
index ec7ac8526f06..ec7ac8526f06 100644
--- a/drivers/video/c2p_planar.c
+++ b/drivers/video/fbdev/c2p_planar.c
diff --git a/drivers/video/carminefb.c b/drivers/video/fbdev/carminefb.c
index 65f7c15f5fdb..65f7c15f5fdb 100644
--- a/drivers/video/carminefb.c
+++ b/drivers/video/fbdev/carminefb.c
diff --git a/drivers/video/carminefb.h b/drivers/video/fbdev/carminefb.h
index 05306de0c6b6..05306de0c6b6 100644
--- a/drivers/video/carminefb.h
+++ b/drivers/video/fbdev/carminefb.h
diff --git a/drivers/video/carminefb_regs.h b/drivers/video/fbdev/carminefb_regs.h
index 045215600b73..045215600b73 100644
--- a/drivers/video/carminefb_regs.h
+++ b/drivers/video/fbdev/carminefb_regs.h
diff --git a/drivers/video/cg14.c b/drivers/video/fbdev/cg14.c
index c79745b136bb..c79745b136bb 100644
--- a/drivers/video/cg14.c
+++ b/drivers/video/fbdev/cg14.c
diff --git a/drivers/video/cg3.c b/drivers/video/fbdev/cg3.c
index 64a89d5747ed..64a89d5747ed 100644
--- a/drivers/video/cg3.c
+++ b/drivers/video/fbdev/cg3.c
diff --git a/drivers/video/cg6.c b/drivers/video/fbdev/cg6.c
index 70781fea092a..70781fea092a 100644
--- a/drivers/video/cg6.c
+++ b/drivers/video/fbdev/cg6.c
diff --git a/drivers/video/chipsfb.c b/drivers/video/fbdev/chipsfb.c
index 206a66b61072..206a66b61072 100644
--- a/drivers/video/chipsfb.c
+++ b/drivers/video/fbdev/chipsfb.c
diff --git a/drivers/video/cirrusfb.c b/drivers/video/fbdev/cirrusfb.c
index d992aa5eb3f0..d992aa5eb3f0 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/fbdev/cirrusfb.c
diff --git a/drivers/video/clps711xfb.c b/drivers/video/fbdev/clps711xfb.c
index f00980607b8f..f00980607b8f 100644
--- a/drivers/video/clps711xfb.c
+++ b/drivers/video/fbdev/clps711xfb.c
diff --git a/drivers/video/cobalt_lcdfb.c b/drivers/video/fbdev/cobalt_lcdfb.c
index d5533f4db1cf..d5533f4db1cf 100644
--- a/drivers/video/cobalt_lcdfb.c
+++ b/drivers/video/fbdev/cobalt_lcdfb.c
diff --git a/drivers/video/controlfb.c b/drivers/video/fbdev/controlfb.c
index fdadef979238..fdadef979238 100644
--- a/drivers/video/controlfb.c
+++ b/drivers/video/fbdev/controlfb.c
diff --git a/drivers/video/controlfb.h b/drivers/video/fbdev/controlfb.h
index 6026c60fc100..6026c60fc100 100644
--- a/drivers/video/controlfb.h
+++ b/drivers/video/fbdev/controlfb.h
diff --git a/drivers/video/fbdev/core/Makefile b/drivers/video/fbdev/core/Makefile
new file mode 100644
index 000000000000..fa306538dac2
--- /dev/null
+++ b/drivers/video/fbdev/core/Makefile
@@ -0,0 +1,16 @@
+obj-y += fb_notify.o
+obj-$(CONFIG_FB) += fb.o
+fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \
+ modedb.o fbcvt.o
+fb-objs := $(fb-y)
+
+obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o
+obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o
+obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o
+obj-$(CONFIG_FB_SYS_FILLRECT) += sysfillrect.o
+obj-$(CONFIG_FB_SYS_COPYAREA) += syscopyarea.o
+obj-$(CONFIG_FB_SYS_IMAGEBLIT) += sysimgblt.o
+obj-$(CONFIG_FB_SYS_FOPS) += fb_sys_fops.o
+obj-$(CONFIG_FB_SVGALIB) += svgalib.o
+obj-$(CONFIG_FB_DDC) += fb_ddc.o
+obj-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o
diff --git a/drivers/video/cfbcopyarea.c b/drivers/video/fbdev/core/cfbcopyarea.c
index bcb57235fcc7..bcb57235fcc7 100644
--- a/drivers/video/cfbcopyarea.c
+++ b/drivers/video/fbdev/core/cfbcopyarea.c
diff --git a/drivers/video/cfbfillrect.c b/drivers/video/fbdev/core/cfbfillrect.c
index ba9f58b2a5e8..ba9f58b2a5e8 100644
--- a/drivers/video/cfbfillrect.c
+++ b/drivers/video/fbdev/core/cfbfillrect.c
diff --git a/drivers/video/cfbimgblt.c b/drivers/video/fbdev/core/cfbimgblt.c
index a2bb276a8b24..a2bb276a8b24 100644
--- a/drivers/video/cfbimgblt.c
+++ b/drivers/video/fbdev/core/cfbimgblt.c
diff --git a/drivers/video/fb_ddc.c b/drivers/video/fbdev/core/fb_ddc.c
index 2b106f046fde..94322ccfedde 100644
--- a/drivers/video/fb_ddc.c
+++ b/drivers/video/fbdev/core/fb_ddc.c
@@ -15,7 +15,7 @@
#include <linux/i2c-algo-bit.h>
#include <linux/slab.h>
-#include "edid.h"
+#include "../edid.h"
#define DDC_ADDR 0x50
diff --git a/drivers/video/fb_defio.c b/drivers/video/fbdev/core/fb_defio.c
index 900aa4ecd617..900aa4ecd617 100644
--- a/drivers/video/fb_defio.c
+++ b/drivers/video/fbdev/core/fb_defio.c
diff --git a/drivers/video/fb_draw.h b/drivers/video/fbdev/core/fb_draw.h
index 624ee115f129..624ee115f129 100644
--- a/drivers/video/fb_draw.h
+++ b/drivers/video/fbdev/core/fb_draw.h
diff --git a/drivers/video/fb_notify.c b/drivers/video/fbdev/core/fb_notify.c
index 74c2da528884..74c2da528884 100644
--- a/drivers/video/fb_notify.c
+++ b/drivers/video/fbdev/core/fb_notify.c
diff --git a/drivers/video/fb_sys_fops.c b/drivers/video/fbdev/core/fb_sys_fops.c
index ff275d7f3eaf..ff275d7f3eaf 100644
--- a/drivers/video/fb_sys_fops.c
+++ b/drivers/video/fbdev/core/fb_sys_fops.c
diff --git a/drivers/video/fbcmap.c b/drivers/video/fbdev/core/fbcmap.c
index f89245b8ba8e..f89245b8ba8e 100644
--- a/drivers/video/fbcmap.c
+++ b/drivers/video/fbdev/core/fbcmap.c
diff --git a/drivers/video/fbcvt.c b/drivers/video/fbdev/core/fbcvt.c
index 7cb715dfc0e1..7cb715dfc0e1 100644
--- a/drivers/video/fbcvt.c
+++ b/drivers/video/fbdev/core/fbcvt.c
diff --git a/drivers/video/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index b6d5008f361f..b6d5008f361f 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
diff --git a/drivers/video/fbmon.c b/drivers/video/fbdev/core/fbmon.c
index 6103fa6fb54f..c204ebe6187e 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbdev/core/fbmon.c
@@ -37,7 +37,7 @@
#include <asm/prom.h>
#include <asm/pci-bridge.h>
#endif
-#include "edid.h"
+#include "../edid.h"
/*
* EDID parser
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbdev/core/fbsysfs.c
index 53444ac19fe0..53444ac19fe0 100644
--- a/drivers/video/fbsysfs.c
+++ b/drivers/video/fbdev/core/fbsysfs.c
diff --git a/drivers/video/modedb.c b/drivers/video/fbdev/core/modedb.c
index a9a907c440d7..a9a907c440d7 100644
--- a/drivers/video/modedb.c
+++ b/drivers/video/fbdev/core/modedb.c
diff --git a/drivers/video/svgalib.c b/drivers/video/fbdev/core/svgalib.c
index 9e01322fabe3..9e01322fabe3 100644
--- a/drivers/video/svgalib.c
+++ b/drivers/video/fbdev/core/svgalib.c
diff --git a/drivers/video/syscopyarea.c b/drivers/video/fbdev/core/syscopyarea.c
index 844a32fd38ed..844a32fd38ed 100644
--- a/drivers/video/syscopyarea.c
+++ b/drivers/video/fbdev/core/syscopyarea.c
diff --git a/drivers/video/sysfillrect.c b/drivers/video/fbdev/core/sysfillrect.c
index 33ee3d34f9d2..33ee3d34f9d2 100644
--- a/drivers/video/sysfillrect.c
+++ b/drivers/video/fbdev/core/sysfillrect.c
diff --git a/drivers/video/sysimgblt.c b/drivers/video/fbdev/core/sysimgblt.c
index a4d05b1b17d7..a4d05b1b17d7 100644
--- a/drivers/video/sysimgblt.c
+++ b/drivers/video/fbdev/core/sysimgblt.c
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/fbdev/cyber2000fb.c
index b0a950f36970..b0a950f36970 100644
--- a/drivers/video/cyber2000fb.c
+++ b/drivers/video/fbdev/cyber2000fb.c
diff --git a/drivers/video/cyber2000fb.h b/drivers/video/fbdev/cyber2000fb.h
index bad69102e774..bad69102e774 100644
--- a/drivers/video/cyber2000fb.h
+++ b/drivers/video/fbdev/cyber2000fb.h
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/fbdev/da8xx-fb.c
index 0c0ba920ea48..6b23508ff0a5 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/fbdev/da8xx-fb.c
@@ -663,15 +663,7 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
(green << info->var.green.offset) |
(blue << info->var.blue.offset);
- switch (info->var.bits_per_pixel) {
- case 16:
- ((u16 *) (info->pseudo_palette))[regno] = v;
- break;
- case 24:
- case 32:
- ((u32 *) (info->pseudo_palette))[regno] = v;
- break;
- }
+ ((u32 *) (info->pseudo_palette))[regno] = v;
if (palette[0] != 0x4000) {
update_hw = 1;
palette[0] = 0x4000;
diff --git a/drivers/video/dnfb.c b/drivers/video/fbdev/dnfb.c
index 3526899da61b..3526899da61b 100644
--- a/drivers/video/dnfb.c
+++ b/drivers/video/fbdev/dnfb.c
diff --git a/drivers/video/edid.h b/drivers/video/fbdev/edid.h
index d03a232d90b2..d03a232d90b2 100644
--- a/drivers/video/edid.h
+++ b/drivers/video/fbdev/edid.h
diff --git a/drivers/video/efifb.c b/drivers/video/fbdev/efifb.c
index ae9618ff6735..ae9618ff6735 100644
--- a/drivers/video/efifb.c
+++ b/drivers/video/fbdev/efifb.c
diff --git a/drivers/video/ep93xx-fb.c b/drivers/video/fbdev/ep93xx-fb.c
index 35a0f533f1a2..35a0f533f1a2 100644
--- a/drivers/video/ep93xx-fb.c
+++ b/drivers/video/fbdev/ep93xx-fb.c
diff --git a/drivers/video/exynos/Kconfig b/drivers/video/fbdev/exynos/Kconfig
index fcf2d48ac6d1..fcf2d48ac6d1 100644
--- a/drivers/video/exynos/Kconfig
+++ b/drivers/video/fbdev/exynos/Kconfig
diff --git a/drivers/video/exynos/Makefile b/drivers/video/fbdev/exynos/Makefile
index b5b1bd228abb..b5b1bd228abb 100644
--- a/drivers/video/exynos/Makefile
+++ b/drivers/video/fbdev/exynos/Makefile
diff --git a/drivers/video/exynos/exynos_mipi_dsi.c b/drivers/video/fbdev/exynos/exynos_mipi_dsi.c
index cee9602f9a7b..cee9602f9a7b 100644
--- a/drivers/video/exynos/exynos_mipi_dsi.c
+++ b/drivers/video/fbdev/exynos/exynos_mipi_dsi.c
diff --git a/drivers/video/exynos/exynos_mipi_dsi_common.c b/drivers/video/fbdev/exynos/exynos_mipi_dsi_common.c
index 85edabfdef5a..85edabfdef5a 100644
--- a/drivers/video/exynos/exynos_mipi_dsi_common.c
+++ b/drivers/video/fbdev/exynos/exynos_mipi_dsi_common.c
diff --git a/drivers/video/exynos/exynos_mipi_dsi_common.h b/drivers/video/fbdev/exynos/exynos_mipi_dsi_common.h
index 412552274df3..412552274df3 100644
--- a/drivers/video/exynos/exynos_mipi_dsi_common.h
+++ b/drivers/video/fbdev/exynos/exynos_mipi_dsi_common.h
diff --git a/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c b/drivers/video/fbdev/exynos/exynos_mipi_dsi_lowlevel.c
index c148d06540c1..c148d06540c1 100644
--- a/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c
+++ b/drivers/video/fbdev/exynos/exynos_mipi_dsi_lowlevel.c
diff --git a/drivers/video/exynos/exynos_mipi_dsi_lowlevel.h b/drivers/video/fbdev/exynos/exynos_mipi_dsi_lowlevel.h
index 85460701c7ea..85460701c7ea 100644
--- a/drivers/video/exynos/exynos_mipi_dsi_lowlevel.h
+++ b/drivers/video/fbdev/exynos/exynos_mipi_dsi_lowlevel.h
diff --git a/drivers/video/exynos/exynos_mipi_dsi_regs.h b/drivers/video/fbdev/exynos/exynos_mipi_dsi_regs.h
index 4227106d3fd0..4227106d3fd0 100644
--- a/drivers/video/exynos/exynos_mipi_dsi_regs.h
+++ b/drivers/video/fbdev/exynos/exynos_mipi_dsi_regs.h
diff --git a/drivers/video/exynos/s6e8ax0.c b/drivers/video/fbdev/exynos/s6e8ax0.c
index 29e70ed3f154..29e70ed3f154 100644
--- a/drivers/video/exynos/s6e8ax0.c
+++ b/drivers/video/fbdev/exynos/s6e8ax0.c
diff --git a/drivers/video/fb-puv3.c b/drivers/video/fbdev/fb-puv3.c
index 6db9ebd042a3..6db9ebd042a3 100644
--- a/drivers/video/fb-puv3.c
+++ b/drivers/video/fbdev/fb-puv3.c
diff --git a/drivers/video/ffb.c b/drivers/video/fbdev/ffb.c
index 4c4ffa61ae26..4c4ffa61ae26 100644
--- a/drivers/video/ffb.c
+++ b/drivers/video/fbdev/ffb.c
diff --git a/drivers/video/fm2fb.c b/drivers/video/fbdev/fm2fb.c
index e69d47af9932..e69d47af9932 100644
--- a/drivers/video/fm2fb.c
+++ b/drivers/video/fbdev/fm2fb.c
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fbdev/fsl-diu-fb.c
index e8758b9c3bcc..e8758b9c3bcc 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fbdev/fsl-diu-fb.c
diff --git a/drivers/video/g364fb.c b/drivers/video/fbdev/g364fb.c
index 223896cc5f7d..223896cc5f7d 100644
--- a/drivers/video/g364fb.c
+++ b/drivers/video/fbdev/g364fb.c
diff --git a/drivers/video/gbefb.c b/drivers/video/fbdev/gbefb.c
index 3ec65a878ac8..3ec65a878ac8 100644
--- a/drivers/video/gbefb.c
+++ b/drivers/video/fbdev/gbefb.c
diff --git a/drivers/video/geode/Kconfig b/drivers/video/fbdev/geode/Kconfig
index 1e8555284786..1e8555284786 100644
--- a/drivers/video/geode/Kconfig
+++ b/drivers/video/fbdev/geode/Kconfig
diff --git a/drivers/video/geode/Makefile b/drivers/video/fbdev/geode/Makefile
index 5c98da126883..5c98da126883 100644
--- a/drivers/video/geode/Makefile
+++ b/drivers/video/fbdev/geode/Makefile
diff --git a/drivers/video/geode/display_gx.c b/drivers/video/fbdev/geode/display_gx.c
index f0af911a096d..f0af911a096d 100644
--- a/drivers/video/geode/display_gx.c
+++ b/drivers/video/fbdev/geode/display_gx.c
diff --git a/drivers/video/geode/display_gx1.c b/drivers/video/fbdev/geode/display_gx1.c
index 926d53eeb549..926d53eeb549 100644
--- a/drivers/video/geode/display_gx1.c
+++ b/drivers/video/fbdev/geode/display_gx1.c
diff --git a/drivers/video/geode/display_gx1.h b/drivers/video/fbdev/geode/display_gx1.h
index 671c05558c79..671c05558c79 100644
--- a/drivers/video/geode/display_gx1.h
+++ b/drivers/video/fbdev/geode/display_gx1.h
diff --git a/drivers/video/geode/geodefb.h b/drivers/video/fbdev/geode/geodefb.h
index ae04820e0c57..ae04820e0c57 100644
--- a/drivers/video/geode/geodefb.h
+++ b/drivers/video/fbdev/geode/geodefb.h
diff --git a/drivers/video/geode/gx1fb_core.c b/drivers/video/fbdev/geode/gx1fb_core.c
index 2794ba11f332..2794ba11f332 100644
--- a/drivers/video/geode/gx1fb_core.c
+++ b/drivers/video/fbdev/geode/gx1fb_core.c
diff --git a/drivers/video/geode/gxfb.h b/drivers/video/fbdev/geode/gxfb.h
index d19e9378b0c0..d19e9378b0c0 100644
--- a/drivers/video/geode/gxfb.h
+++ b/drivers/video/fbdev/geode/gxfb.h
diff --git a/drivers/video/geode/gxfb_core.c b/drivers/video/fbdev/geode/gxfb_core.c
index 1790f14bab15..1790f14bab15 100644
--- a/drivers/video/geode/gxfb_core.c
+++ b/drivers/video/fbdev/geode/gxfb_core.c
diff --git a/drivers/video/geode/lxfb.h b/drivers/video/fbdev/geode/lxfb.h
index cfcd8090f313..cfcd8090f313 100644
--- a/drivers/video/geode/lxfb.h
+++ b/drivers/video/fbdev/geode/lxfb.h
diff --git a/drivers/video/geode/lxfb_core.c b/drivers/video/fbdev/geode/lxfb_core.c
index 9e1d19d673a1..9e1d19d673a1 100644
--- a/drivers/video/geode/lxfb_core.c
+++ b/drivers/video/fbdev/geode/lxfb_core.c
diff --git a/drivers/video/geode/lxfb_ops.c b/drivers/video/fbdev/geode/lxfb_ops.c
index 79e9abc72b83..79e9abc72b83 100644
--- a/drivers/video/geode/lxfb_ops.c
+++ b/drivers/video/fbdev/geode/lxfb_ops.c
diff --git a/drivers/video/geode/suspend_gx.c b/drivers/video/fbdev/geode/suspend_gx.c
index 1bb043d70c64..1bb043d70c64 100644
--- a/drivers/video/geode/suspend_gx.c
+++ b/drivers/video/fbdev/geode/suspend_gx.c
diff --git a/drivers/video/geode/video_cs5530.c b/drivers/video/fbdev/geode/video_cs5530.c
index 649c3943d431..649c3943d431 100644
--- a/drivers/video/geode/video_cs5530.c
+++ b/drivers/video/fbdev/geode/video_cs5530.c
diff --git a/drivers/video/geode/video_cs5530.h b/drivers/video/fbdev/geode/video_cs5530.h
index 56cecca7f1ce..56cecca7f1ce 100644
--- a/drivers/video/geode/video_cs5530.h
+++ b/drivers/video/fbdev/geode/video_cs5530.h
diff --git a/drivers/video/geode/video_gx.c b/drivers/video/fbdev/geode/video_gx.c
index 6082f653c68a..6082f653c68a 100644
--- a/drivers/video/geode/video_gx.c
+++ b/drivers/video/fbdev/geode/video_gx.c
diff --git a/drivers/video/goldfishfb.c b/drivers/video/fbdev/goldfishfb.c
index 7f6c9e6cfc6c..7f6c9e6cfc6c 100644
--- a/drivers/video/goldfishfb.c
+++ b/drivers/video/fbdev/goldfishfb.c
diff --git a/drivers/video/grvga.c b/drivers/video/fbdev/grvga.c
index c078701f15f6..c078701f15f6 100644
--- a/drivers/video/grvga.c
+++ b/drivers/video/fbdev/grvga.c
diff --git a/drivers/video/gxt4500.c b/drivers/video/fbdev/gxt4500.c
index 135d78a02588..135d78a02588 100644
--- a/drivers/video/gxt4500.c
+++ b/drivers/video/fbdev/gxt4500.c
diff --git a/drivers/video/hecubafb.c b/drivers/video/fbdev/hecubafb.c
index f64120ec9192..f64120ec9192 100644
--- a/drivers/video/hecubafb.c
+++ b/drivers/video/fbdev/hecubafb.c
diff --git a/drivers/video/hgafb.c b/drivers/video/fbdev/hgafb.c
index 5ff9fe2116a4..5ff9fe2116a4 100644
--- a/drivers/video/hgafb.c
+++ b/drivers/video/fbdev/hgafb.c
diff --git a/drivers/video/hitfb.c b/drivers/video/fbdev/hitfb.c
index a648d5186c6e..a648d5186c6e 100644
--- a/drivers/video/hitfb.c
+++ b/drivers/video/fbdev/hitfb.c
diff --git a/drivers/video/hpfb.c b/drivers/video/fbdev/hpfb.c
index a1b7e5fa9b09..a1b7e5fa9b09 100644
--- a/drivers/video/hpfb.c
+++ b/drivers/video/fbdev/hpfb.c
diff --git a/drivers/video/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c
index e23392ec5af3..e23392ec5af3 100644
--- a/drivers/video/hyperv_fb.c
+++ b/drivers/video/fbdev/hyperv_fb.c
diff --git a/drivers/video/i740_reg.h b/drivers/video/fbdev/i740_reg.h
index 91bac76549d7..91bac76549d7 100644
--- a/drivers/video/i740_reg.h
+++ b/drivers/video/fbdev/i740_reg.h
diff --git a/drivers/video/i740fb.c b/drivers/video/fbdev/i740fb.c
index ca7c9df193b0..ca7c9df193b0 100644
--- a/drivers/video/i740fb.c
+++ b/drivers/video/fbdev/i740fb.c
diff --git a/drivers/video/i810/Makefile b/drivers/video/fbdev/i810/Makefile
index 96e08c8ded97..96e08c8ded97 100644
--- a/drivers/video/i810/Makefile
+++ b/drivers/video/fbdev/i810/Makefile
diff --git a/drivers/video/i810/i810-i2c.c b/drivers/video/fbdev/i810/i810-i2c.c
index 7db17d0d8a8c..7db17d0d8a8c 100644
--- a/drivers/video/i810/i810-i2c.c
+++ b/drivers/video/fbdev/i810/i810-i2c.c
diff --git a/drivers/video/i810/i810.h b/drivers/video/fbdev/i810/i810.h
index 1414b73ac55b..1414b73ac55b 100644
--- a/drivers/video/i810/i810.h
+++ b/drivers/video/fbdev/i810/i810.h
diff --git a/drivers/video/i810/i810_accel.c b/drivers/video/fbdev/i810/i810_accel.c
index 7672d2ea9b35..7672d2ea9b35 100644
--- a/drivers/video/i810/i810_accel.c
+++ b/drivers/video/fbdev/i810/i810_accel.c
diff --git a/drivers/video/i810/i810_dvt.c b/drivers/video/fbdev/i810/i810_dvt.c
index b4b3670667ab..b4b3670667ab 100644
--- a/drivers/video/i810/i810_dvt.c
+++ b/drivers/video/fbdev/i810/i810_dvt.c
diff --git a/drivers/video/i810/i810_gtf.c b/drivers/video/fbdev/i810/i810_gtf.c
index 9743d51e7f8c..9743d51e7f8c 100644
--- a/drivers/video/i810/i810_gtf.c
+++ b/drivers/video/fbdev/i810/i810_gtf.c
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/fbdev/i810/i810_main.c
index bb674e431741..bb674e431741 100644
--- a/drivers/video/i810/i810_main.c
+++ b/drivers/video/fbdev/i810/i810_main.c
diff --git a/drivers/video/i810/i810_main.h b/drivers/video/fbdev/i810/i810_main.h
index a25afaa534ba..a25afaa534ba 100644
--- a/drivers/video/i810/i810_main.h
+++ b/drivers/video/fbdev/i810/i810_main.h
diff --git a/drivers/video/i810/i810_regs.h b/drivers/video/fbdev/i810/i810_regs.h
index 91c6bd9d0d0d..91c6bd9d0d0d 100644
--- a/drivers/video/i810/i810_regs.h
+++ b/drivers/video/fbdev/i810/i810_regs.h
diff --git a/drivers/video/igafb.c b/drivers/video/fbdev/igafb.c
index 486f18897414..486f18897414 100644
--- a/drivers/video/igafb.c
+++ b/drivers/video/fbdev/igafb.c
diff --git a/drivers/video/imsttfb.c b/drivers/video/fbdev/imsttfb.c
index aae10ce74f14..aae10ce74f14 100644
--- a/drivers/video/imsttfb.c
+++ b/drivers/video/fbdev/imsttfb.c
diff --git a/drivers/video/imxfb.c b/drivers/video/fbdev/imxfb.c
index f6e621684953..f6e621684953 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/fbdev/imxfb.c
diff --git a/drivers/video/intelfb/Makefile b/drivers/video/fbdev/intelfb/Makefile
index f7d631ebee8e..f7d631ebee8e 100644
--- a/drivers/video/intelfb/Makefile
+++ b/drivers/video/fbdev/intelfb/Makefile
diff --git a/drivers/video/intelfb/intelfb.h b/drivers/video/fbdev/intelfb/intelfb.h
index 6b51175629c7..6b51175629c7 100644
--- a/drivers/video/intelfb/intelfb.h
+++ b/drivers/video/fbdev/intelfb/intelfb.h
diff --git a/drivers/video/intelfb/intelfb_i2c.c b/drivers/video/fbdev/intelfb/intelfb_i2c.c
index 3300bd31d9d7..3300bd31d9d7 100644
--- a/drivers/video/intelfb/intelfb_i2c.c
+++ b/drivers/video/fbdev/intelfb/intelfb_i2c.c
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/fbdev/intelfb/intelfbdrv.c
index b847d530471a..b847d530471a 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/fbdev/intelfb/intelfbdrv.c
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/fbdev/intelfb/intelfbhw.c
index fbad61da359f..fbad61da359f 100644
--- a/drivers/video/intelfb/intelfbhw.c
+++ b/drivers/video/fbdev/intelfb/intelfbhw.c
diff --git a/drivers/video/intelfb/intelfbhw.h b/drivers/video/fbdev/intelfb/intelfbhw.h
index 216ca20f259f..216ca20f259f 100644
--- a/drivers/video/intelfb/intelfbhw.h
+++ b/drivers/video/fbdev/intelfb/intelfbhw.h
diff --git a/drivers/video/jz4740_fb.c b/drivers/video/fbdev/jz4740_fb.c
index 87790e9644d0..87790e9644d0 100644
--- a/drivers/video/jz4740_fb.c
+++ b/drivers/video/fbdev/jz4740_fb.c
diff --git a/drivers/video/kyro/Makefile b/drivers/video/fbdev/kyro/Makefile
index 2fd66f551bae..2fd66f551bae 100644
--- a/drivers/video/kyro/Makefile
+++ b/drivers/video/fbdev/kyro/Makefile
diff --git a/drivers/video/kyro/STG4000InitDevice.c b/drivers/video/fbdev/kyro/STG4000InitDevice.c
index 1d3f2080aa6f..1d3f2080aa6f 100644
--- a/drivers/video/kyro/STG4000InitDevice.c
+++ b/drivers/video/fbdev/kyro/STG4000InitDevice.c
diff --git a/drivers/video/kyro/STG4000Interface.h b/drivers/video/fbdev/kyro/STG4000Interface.h
index b7c83d5dfb13..b7c83d5dfb13 100644
--- a/drivers/video/kyro/STG4000Interface.h
+++ b/drivers/video/fbdev/kyro/STG4000Interface.h
diff --git a/drivers/video/kyro/STG4000OverlayDevice.c b/drivers/video/fbdev/kyro/STG4000OverlayDevice.c
index 0aeeaa10708b..0aeeaa10708b 100644
--- a/drivers/video/kyro/STG4000OverlayDevice.c
+++ b/drivers/video/fbdev/kyro/STG4000OverlayDevice.c
diff --git a/drivers/video/kyro/STG4000Ramdac.c b/drivers/video/fbdev/kyro/STG4000Ramdac.c
index e6ad037e4396..e6ad037e4396 100644
--- a/drivers/video/kyro/STG4000Ramdac.c
+++ b/drivers/video/fbdev/kyro/STG4000Ramdac.c
diff --git a/drivers/video/kyro/STG4000Reg.h b/drivers/video/fbdev/kyro/STG4000Reg.h
index 50f4670e9252..50f4670e9252 100644
--- a/drivers/video/kyro/STG4000Reg.h
+++ b/drivers/video/fbdev/kyro/STG4000Reg.h
diff --git a/drivers/video/kyro/STG4000VTG.c b/drivers/video/fbdev/kyro/STG4000VTG.c
index bd389709d234..bd389709d234 100644
--- a/drivers/video/kyro/STG4000VTG.c
+++ b/drivers/video/fbdev/kyro/STG4000VTG.c
diff --git a/drivers/video/kyro/fbdev.c b/drivers/video/fbdev/kyro/fbdev.c
index 65041e15fd59..65041e15fd59 100644
--- a/drivers/video/kyro/fbdev.c
+++ b/drivers/video/fbdev/kyro/fbdev.c
diff --git a/drivers/video/leo.c b/drivers/video/fbdev/leo.c
index 2c7f7d479fe2..2c7f7d479fe2 100644
--- a/drivers/video/leo.c
+++ b/drivers/video/fbdev/leo.c
diff --git a/drivers/video/macfb.c b/drivers/video/fbdev/macfb.c
index cda7587cbc86..cda7587cbc86 100644
--- a/drivers/video/macfb.c
+++ b/drivers/video/fbdev/macfb.c
diff --git a/drivers/video/macmodes.c b/drivers/video/fbdev/macmodes.c
index af86c081d2be..af86c081d2be 100644
--- a/drivers/video/macmodes.c
+++ b/drivers/video/fbdev/macmodes.c
diff --git a/drivers/video/macmodes.h b/drivers/video/fbdev/macmodes.h
index b86ba08aac9e..b86ba08aac9e 100644
--- a/drivers/video/macmodes.h
+++ b/drivers/video/fbdev/macmodes.h
diff --git a/drivers/video/matrox/Makefile b/drivers/video/fbdev/matrox/Makefile
index f9c00ebe2530..f9c00ebe2530 100644
--- a/drivers/video/matrox/Makefile
+++ b/drivers/video/fbdev/matrox/Makefile
diff --git a/drivers/video/matrox/g450_pll.c b/drivers/video/fbdev/matrox/g450_pll.c
index c15f8a57498e..c15f8a57498e 100644
--- a/drivers/video/matrox/g450_pll.c
+++ b/drivers/video/fbdev/matrox/g450_pll.c
diff --git a/drivers/video/matrox/g450_pll.h b/drivers/video/fbdev/matrox/g450_pll.h
index aac615d18440..aac615d18440 100644
--- a/drivers/video/matrox/g450_pll.h
+++ b/drivers/video/fbdev/matrox/g450_pll.h
diff --git a/drivers/video/matrox/i2c-matroxfb.c b/drivers/video/fbdev/matrox/i2c-matroxfb.c
index 0fb280ead3dc..0fb280ead3dc 100644
--- a/drivers/video/matrox/i2c-matroxfb.c
+++ b/drivers/video/fbdev/matrox/i2c-matroxfb.c
diff --git a/drivers/video/matrox/matroxfb_DAC1064.c b/drivers/video/fbdev/matrox/matroxfb_DAC1064.c
index a01147fdf270..a01147fdf270 100644
--- a/drivers/video/matrox/matroxfb_DAC1064.c
+++ b/drivers/video/fbdev/matrox/matroxfb_DAC1064.c
diff --git a/drivers/video/matrox/matroxfb_DAC1064.h b/drivers/video/fbdev/matrox/matroxfb_DAC1064.h
index 1e6e45b57b78..1e6e45b57b78 100644
--- a/drivers/video/matrox/matroxfb_DAC1064.h
+++ b/drivers/video/fbdev/matrox/matroxfb_DAC1064.h
diff --git a/drivers/video/matrox/matroxfb_Ti3026.c b/drivers/video/fbdev/matrox/matroxfb_Ti3026.c
index 195ad7cac1ba..195ad7cac1ba 100644
--- a/drivers/video/matrox/matroxfb_Ti3026.c
+++ b/drivers/video/fbdev/matrox/matroxfb_Ti3026.c
diff --git a/drivers/video/matrox/matroxfb_Ti3026.h b/drivers/video/fbdev/matrox/matroxfb_Ti3026.h
index 27872aaa0a17..27872aaa0a17 100644
--- a/drivers/video/matrox/matroxfb_Ti3026.h
+++ b/drivers/video/fbdev/matrox/matroxfb_Ti3026.h
diff --git a/drivers/video/matrox/matroxfb_accel.c b/drivers/video/fbdev/matrox/matroxfb_accel.c
index 0d5cb85d071a..0d5cb85d071a 100644
--- a/drivers/video/matrox/matroxfb_accel.c
+++ b/drivers/video/fbdev/matrox/matroxfb_accel.c
diff --git a/drivers/video/matrox/matroxfb_accel.h b/drivers/video/fbdev/matrox/matroxfb_accel.h
index 1e418e62c22d..1e418e62c22d 100644
--- a/drivers/video/matrox/matroxfb_accel.h
+++ b/drivers/video/fbdev/matrox/matroxfb_accel.h
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/fbdev/matrox/matroxfb_base.c
index 7116c5309c7d..7116c5309c7d 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/fbdev/matrox/matroxfb_base.c
diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/fbdev/matrox/matroxfb_base.h
index 556d96ce40bf..556d96ce40bf 100644
--- a/drivers/video/matrox/matroxfb_base.h
+++ b/drivers/video/fbdev/matrox/matroxfb_base.h
diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/fbdev/matrox/matroxfb_crtc2.c
index 02796a4317a9..02796a4317a9 100644
--- a/drivers/video/matrox/matroxfb_crtc2.c
+++ b/drivers/video/fbdev/matrox/matroxfb_crtc2.c
diff --git a/drivers/video/matrox/matroxfb_crtc2.h b/drivers/video/fbdev/matrox/matroxfb_crtc2.h
index 1005582e843e..1005582e843e 100644
--- a/drivers/video/matrox/matroxfb_crtc2.h
+++ b/drivers/video/fbdev/matrox/matroxfb_crtc2.h
diff --git a/drivers/video/matrox/matroxfb_g450.c b/drivers/video/fbdev/matrox/matroxfb_g450.c
index cff0546ea6fd..cff0546ea6fd 100644
--- a/drivers/video/matrox/matroxfb_g450.c
+++ b/drivers/video/fbdev/matrox/matroxfb_g450.c
diff --git a/drivers/video/matrox/matroxfb_g450.h b/drivers/video/fbdev/matrox/matroxfb_g450.h
index 3a3e654444b8..3a3e654444b8 100644
--- a/drivers/video/matrox/matroxfb_g450.h
+++ b/drivers/video/fbdev/matrox/matroxfb_g450.h
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/fbdev/matrox/matroxfb_maven.c
index ee41a0f276b2..ee41a0f276b2 100644
--- a/drivers/video/matrox/matroxfb_maven.c
+++ b/drivers/video/fbdev/matrox/matroxfb_maven.c
diff --git a/drivers/video/matrox/matroxfb_maven.h b/drivers/video/fbdev/matrox/matroxfb_maven.h
index 99eddec9f30c..99eddec9f30c 100644
--- a/drivers/video/matrox/matroxfb_maven.h
+++ b/drivers/video/fbdev/matrox/matroxfb_maven.h
diff --git a/drivers/video/matrox/matroxfb_misc.c b/drivers/video/fbdev/matrox/matroxfb_misc.c
index 9948ca2a3046..9948ca2a3046 100644
--- a/drivers/video/matrox/matroxfb_misc.c
+++ b/drivers/video/fbdev/matrox/matroxfb_misc.c
diff --git a/drivers/video/matrox/matroxfb_misc.h b/drivers/video/fbdev/matrox/matroxfb_misc.h
index 351c823f1f74..351c823f1f74 100644
--- a/drivers/video/matrox/matroxfb_misc.h
+++ b/drivers/video/fbdev/matrox/matroxfb_misc.h
diff --git a/drivers/video/maxinefb.c b/drivers/video/fbdev/maxinefb.c
index 5cf52d3c8e75..5cf52d3c8e75 100644
--- a/drivers/video/maxinefb.c
+++ b/drivers/video/fbdev/maxinefb.c
diff --git a/drivers/video/mb862xx/Makefile b/drivers/video/fbdev/mb862xx/Makefile
index 5707ed0e31a7..5707ed0e31a7 100644
--- a/drivers/video/mb862xx/Makefile
+++ b/drivers/video/fbdev/mb862xx/Makefile
diff --git a/drivers/video/mb862xx/mb862xx-i2c.c b/drivers/video/fbdev/mb862xx/mb862xx-i2c.c
index c87e17afb3e2..c87e17afb3e2 100644
--- a/drivers/video/mb862xx/mb862xx-i2c.c
+++ b/drivers/video/fbdev/mb862xx/mb862xx-i2c.c
diff --git a/drivers/video/mb862xx/mb862xx_reg.h b/drivers/video/fbdev/mb862xx/mb862xx_reg.h
index 9df48b8edc94..9df48b8edc94 100644
--- a/drivers/video/mb862xx/mb862xx_reg.h
+++ b/drivers/video/fbdev/mb862xx/mb862xx_reg.h
diff --git a/drivers/video/mb862xx/mb862xxfb.h b/drivers/video/fbdev/mb862xx/mb862xxfb.h
index 8550630c1e01..8550630c1e01 100644
--- a/drivers/video/mb862xx/mb862xxfb.h
+++ b/drivers/video/fbdev/mb862xx/mb862xxfb.h
diff --git a/drivers/video/mb862xx/mb862xxfb_accel.c b/drivers/video/fbdev/mb862xx/mb862xxfb_accel.c
index fe92eed6da70..fe92eed6da70 100644
--- a/drivers/video/mb862xx/mb862xxfb_accel.c
+++ b/drivers/video/fbdev/mb862xx/mb862xxfb_accel.c
diff --git a/drivers/video/mb862xx/mb862xxfb_accel.h b/drivers/video/fbdev/mb862xx/mb862xxfb_accel.h
index 96a2dfef0f60..96a2dfef0f60 100644
--- a/drivers/video/mb862xx/mb862xxfb_accel.h
+++ b/drivers/video/fbdev/mb862xx/mb862xxfb_accel.h
diff --git a/drivers/video/mb862xx/mb862xxfbdrv.c b/drivers/video/fbdev/mb862xx/mb862xxfbdrv.c
index 0cd4c3318511..0cd4c3318511 100644
--- a/drivers/video/mb862xx/mb862xxfbdrv.c
+++ b/drivers/video/fbdev/mb862xx/mb862xxfbdrv.c
diff --git a/drivers/video/mbx/Makefile b/drivers/video/fbdev/mbx/Makefile
index 16c1165cf9c7..16c1165cf9c7 100644
--- a/drivers/video/mbx/Makefile
+++ b/drivers/video/fbdev/mbx/Makefile
diff --git a/drivers/video/mbx/mbxdebugfs.c b/drivers/video/fbdev/mbx/mbxdebugfs.c
index 4449f249b0e7..4449f249b0e7 100644
--- a/drivers/video/mbx/mbxdebugfs.c
+++ b/drivers/video/fbdev/mbx/mbxdebugfs.c
diff --git a/drivers/video/mbx/mbxfb.c b/drivers/video/fbdev/mbx/mbxfb.c
index f0a5392f5fd3..f0a5392f5fd3 100644
--- a/drivers/video/mbx/mbxfb.c
+++ b/drivers/video/fbdev/mbx/mbxfb.c
diff --git a/drivers/video/mbx/reg_bits.h b/drivers/video/fbdev/mbx/reg_bits.h
index 5f14b4befd71..5f14b4befd71 100644
--- a/drivers/video/mbx/reg_bits.h
+++ b/drivers/video/fbdev/mbx/reg_bits.h
diff --git a/drivers/video/mbx/regs.h b/drivers/video/fbdev/mbx/regs.h
index 063099d48839..063099d48839 100644
--- a/drivers/video/mbx/regs.h
+++ b/drivers/video/fbdev/mbx/regs.h
diff --git a/drivers/video/metronomefb.c b/drivers/video/fbdev/metronomefb.c
index 195cc2db4c2c..195cc2db4c2c 100644
--- a/drivers/video/metronomefb.c
+++ b/drivers/video/fbdev/metronomefb.c
diff --git a/drivers/video/mmp/Kconfig b/drivers/video/fbdev/mmp/Kconfig
index e9ea39e13722..d4a4ffc24749 100644
--- a/drivers/video/mmp/Kconfig
+++ b/drivers/video/fbdev/mmp/Kconfig
@@ -5,7 +5,7 @@ menuconfig MMP_DISP
Marvell Display Subsystem support.
if MMP_DISP
-source "drivers/video/mmp/hw/Kconfig"
-source "drivers/video/mmp/panel/Kconfig"
-source "drivers/video/mmp/fb/Kconfig"
+source "drivers/video/fbdev/mmp/hw/Kconfig"
+source "drivers/video/fbdev/mmp/panel/Kconfig"
+source "drivers/video/fbdev/mmp/fb/Kconfig"
endif
diff --git a/drivers/video/mmp/Makefile b/drivers/video/fbdev/mmp/Makefile
index a014cb358bf8..a014cb358bf8 100644
--- a/drivers/video/mmp/Makefile
+++ b/drivers/video/fbdev/mmp/Makefile
diff --git a/drivers/video/mmp/core.c b/drivers/video/fbdev/mmp/core.c
index b563b920f159..b563b920f159 100644
--- a/drivers/video/mmp/core.c
+++ b/drivers/video/fbdev/mmp/core.c
diff --git a/drivers/video/mmp/fb/Kconfig b/drivers/video/fbdev/mmp/fb/Kconfig
index 9b0141f105f5..9b0141f105f5 100644
--- a/drivers/video/mmp/fb/Kconfig
+++ b/drivers/video/fbdev/mmp/fb/Kconfig
diff --git a/drivers/video/mmp/fb/Makefile b/drivers/video/fbdev/mmp/fb/Makefile
index 709fd1f76abe..709fd1f76abe 100644
--- a/drivers/video/mmp/fb/Makefile
+++ b/drivers/video/fbdev/mmp/fb/Makefile
diff --git a/drivers/video/mmp/fb/mmpfb.c b/drivers/video/fbdev/mmp/fb/mmpfb.c
index 7ab31eb76a8c..7ab31eb76a8c 100644
--- a/drivers/video/mmp/fb/mmpfb.c
+++ b/drivers/video/fbdev/mmp/fb/mmpfb.c
diff --git a/drivers/video/mmp/fb/mmpfb.h b/drivers/video/fbdev/mmp/fb/mmpfb.h
index 88c23c10a9ec..88c23c10a9ec 100644
--- a/drivers/video/mmp/fb/mmpfb.h
+++ b/drivers/video/fbdev/mmp/fb/mmpfb.h
diff --git a/drivers/video/mmp/hw/Kconfig b/drivers/video/fbdev/mmp/hw/Kconfig
index 02f109a20cd0..02f109a20cd0 100644
--- a/drivers/video/mmp/hw/Kconfig
+++ b/drivers/video/fbdev/mmp/hw/Kconfig
diff --git a/drivers/video/mmp/hw/Makefile b/drivers/video/fbdev/mmp/hw/Makefile
index 0000a714fedf..0000a714fedf 100644
--- a/drivers/video/mmp/hw/Makefile
+++ b/drivers/video/fbdev/mmp/hw/Makefile
diff --git a/drivers/video/mmp/hw/mmp_ctrl.c b/drivers/video/fbdev/mmp/hw/mmp_ctrl.c
index 8621a9f2bdcc..8621a9f2bdcc 100644
--- a/drivers/video/mmp/hw/mmp_ctrl.c
+++ b/drivers/video/fbdev/mmp/hw/mmp_ctrl.c
diff --git a/drivers/video/mmp/hw/mmp_ctrl.h b/drivers/video/fbdev/mmp/hw/mmp_ctrl.h
index 53301cfdb1ae..53301cfdb1ae 100644
--- a/drivers/video/mmp/hw/mmp_ctrl.h
+++ b/drivers/video/fbdev/mmp/hw/mmp_ctrl.h
diff --git a/drivers/video/mmp/hw/mmp_spi.c b/drivers/video/fbdev/mmp/hw/mmp_spi.c
index e62ca7bf0d5e..e62ca7bf0d5e 100644
--- a/drivers/video/mmp/hw/mmp_spi.c
+++ b/drivers/video/fbdev/mmp/hw/mmp_spi.c
diff --git a/drivers/video/mmp/panel/Kconfig b/drivers/video/fbdev/mmp/panel/Kconfig
index 4b2c4f457b11..4b2c4f457b11 100644
--- a/drivers/video/mmp/panel/Kconfig
+++ b/drivers/video/fbdev/mmp/panel/Kconfig
diff --git a/drivers/video/mmp/panel/Makefile b/drivers/video/fbdev/mmp/panel/Makefile
index 2f91611c7e5e..2f91611c7e5e 100644
--- a/drivers/video/mmp/panel/Makefile
+++ b/drivers/video/fbdev/mmp/panel/Makefile
diff --git a/drivers/video/mmp/panel/tpo_tj032md01bw.c b/drivers/video/fbdev/mmp/panel/tpo_tj032md01bw.c
index 998978b08f5e..998978b08f5e 100644
--- a/drivers/video/mmp/panel/tpo_tj032md01bw.c
+++ b/drivers/video/fbdev/mmp/panel/tpo_tj032md01bw.c
diff --git a/drivers/video/msm/Makefile b/drivers/video/fbdev/msm/Makefile
index 802d6ae523fb..802d6ae523fb 100644
--- a/drivers/video/msm/Makefile
+++ b/drivers/video/fbdev/msm/Makefile
diff --git a/drivers/video/msm/mddi.c b/drivers/video/fbdev/msm/mddi.c
index e0f8011a3c4b..e0f8011a3c4b 100644
--- a/drivers/video/msm/mddi.c
+++ b/drivers/video/fbdev/msm/mddi.c
diff --git a/drivers/video/msm/mddi_client_dummy.c b/drivers/video/fbdev/msm/mddi_client_dummy.c
index f1b0dfcc9717..f1b0dfcc9717 100644
--- a/drivers/video/msm/mddi_client_dummy.c
+++ b/drivers/video/fbdev/msm/mddi_client_dummy.c
diff --git a/drivers/video/msm/mddi_client_nt35399.c b/drivers/video/fbdev/msm/mddi_client_nt35399.c
index f96df32e5509..f96df32e5509 100644
--- a/drivers/video/msm/mddi_client_nt35399.c
+++ b/drivers/video/fbdev/msm/mddi_client_nt35399.c
diff --git a/drivers/video/msm/mddi_client_toshiba.c b/drivers/video/fbdev/msm/mddi_client_toshiba.c
index 061d7dfebbf3..061d7dfebbf3 100644
--- a/drivers/video/msm/mddi_client_toshiba.c
+++ b/drivers/video/fbdev/msm/mddi_client_toshiba.c
diff --git a/drivers/video/msm/mddi_hw.h b/drivers/video/fbdev/msm/mddi_hw.h
index 45cc01fc1e7f..45cc01fc1e7f 100644
--- a/drivers/video/msm/mddi_hw.h
+++ b/drivers/video/fbdev/msm/mddi_hw.h
diff --git a/drivers/video/msm/mdp.c b/drivers/video/fbdev/msm/mdp.c
index 113c7876c855..113c7876c855 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/fbdev/msm/mdp.c
diff --git a/drivers/video/msm/mdp_csc_table.h b/drivers/video/fbdev/msm/mdp_csc_table.h
index d1cde30ead52..d1cde30ead52 100644
--- a/drivers/video/msm/mdp_csc_table.h
+++ b/drivers/video/fbdev/msm/mdp_csc_table.h
diff --git a/drivers/video/msm/mdp_hw.h b/drivers/video/fbdev/msm/mdp_hw.h
index 35848d741001..35848d741001 100644
--- a/drivers/video/msm/mdp_hw.h
+++ b/drivers/video/fbdev/msm/mdp_hw.h
diff --git a/drivers/video/msm/mdp_ppp.c b/drivers/video/fbdev/msm/mdp_ppp.c
index be6079cdfbb6..be6079cdfbb6 100644
--- a/drivers/video/msm/mdp_ppp.c
+++ b/drivers/video/fbdev/msm/mdp_ppp.c
diff --git a/drivers/video/msm/mdp_scale_tables.c b/drivers/video/fbdev/msm/mdp_scale_tables.c
index 604783b2e17c..604783b2e17c 100644
--- a/drivers/video/msm/mdp_scale_tables.c
+++ b/drivers/video/fbdev/msm/mdp_scale_tables.c
diff --git a/drivers/video/msm/mdp_scale_tables.h b/drivers/video/fbdev/msm/mdp_scale_tables.h
index 34077b1af603..34077b1af603 100644
--- a/drivers/video/msm/mdp_scale_tables.h
+++ b/drivers/video/fbdev/msm/mdp_scale_tables.h
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/fbdev/msm/msm_fb.c
index 1374803fbcd9..1374803fbcd9 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/fbdev/msm/msm_fb.c
diff --git a/drivers/video/mx3fb.c b/drivers/video/fbdev/mx3fb.c
index 142e860fb527..142e860fb527 100644
--- a/drivers/video/mx3fb.c
+++ b/drivers/video/fbdev/mx3fb.c
diff --git a/drivers/video/mxsfb.c b/drivers/video/fbdev/mxsfb.c
index accf48a2cce4..accf48a2cce4 100644
--- a/drivers/video/mxsfb.c
+++ b/drivers/video/fbdev/mxsfb.c
diff --git a/drivers/video/n411.c b/drivers/video/fbdev/n411.c
index 935830fea7b6..935830fea7b6 100644
--- a/drivers/video/n411.c
+++ b/drivers/video/fbdev/n411.c
diff --git a/drivers/video/neofb.c b/drivers/video/fbdev/neofb.c
index 44f99a60bb9b..44f99a60bb9b 100644
--- a/drivers/video/neofb.c
+++ b/drivers/video/fbdev/neofb.c
diff --git a/drivers/video/nuc900fb.c b/drivers/video/fbdev/nuc900fb.c
index 478f9808dee4..478f9808dee4 100644
--- a/drivers/video/nuc900fb.c
+++ b/drivers/video/fbdev/nuc900fb.c
diff --git a/drivers/video/nuc900fb.h b/drivers/video/fbdev/nuc900fb.h
index 9a1ca6dbb6b2..9a1ca6dbb6b2 100644
--- a/drivers/video/nuc900fb.h
+++ b/drivers/video/fbdev/nuc900fb.h
diff --git a/drivers/video/nvidia/Makefile b/drivers/video/fbdev/nvidia/Makefile
index ca47432113e0..ca47432113e0 100644
--- a/drivers/video/nvidia/Makefile
+++ b/drivers/video/fbdev/nvidia/Makefile
diff --git a/drivers/video/nvidia/nv_accel.c b/drivers/video/fbdev/nvidia/nv_accel.c
index ad6472a894ea..ad6472a894ea 100644
--- a/drivers/video/nvidia/nv_accel.c
+++ b/drivers/video/fbdev/nvidia/nv_accel.c
diff --git a/drivers/video/nvidia/nv_backlight.c b/drivers/video/fbdev/nvidia/nv_backlight.c
index 8471008aa6ff..8471008aa6ff 100644
--- a/drivers/video/nvidia/nv_backlight.c
+++ b/drivers/video/fbdev/nvidia/nv_backlight.c
diff --git a/drivers/video/nvidia/nv_dma.h b/drivers/video/fbdev/nvidia/nv_dma.h
index a7ed1c0acbbb..a7ed1c0acbbb 100644
--- a/drivers/video/nvidia/nv_dma.h
+++ b/drivers/video/fbdev/nvidia/nv_dma.h
diff --git a/drivers/video/nvidia/nv_hw.c b/drivers/video/fbdev/nvidia/nv_hw.c
index 81c80ac3c76f..81c80ac3c76f 100644
--- a/drivers/video/nvidia/nv_hw.c
+++ b/drivers/video/fbdev/nvidia/nv_hw.c
diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/fbdev/nvidia/nv_i2c.c
index d7994a173245..d7994a173245 100644
--- a/drivers/video/nvidia/nv_i2c.c
+++ b/drivers/video/fbdev/nvidia/nv_i2c.c
diff --git a/drivers/video/nvidia/nv_local.h b/drivers/video/fbdev/nvidia/nv_local.h
index 68e508daa417..68e508daa417 100644
--- a/drivers/video/nvidia/nv_local.h
+++ b/drivers/video/fbdev/nvidia/nv_local.h
diff --git a/drivers/video/nvidia/nv_of.c b/drivers/video/fbdev/nvidia/nv_of.c
index 3bc13df4b120..3bc13df4b120 100644
--- a/drivers/video/nvidia/nv_of.c
+++ b/drivers/video/fbdev/nvidia/nv_of.c
diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/fbdev/nvidia/nv_proto.h
index ff5c410355ea..ff5c410355ea 100644
--- a/drivers/video/nvidia/nv_proto.h
+++ b/drivers/video/fbdev/nvidia/nv_proto.h
diff --git a/drivers/video/nvidia/nv_setup.c b/drivers/video/fbdev/nvidia/nv_setup.c
index 2f2e162134fa..2f2e162134fa 100644
--- a/drivers/video/nvidia/nv_setup.c
+++ b/drivers/video/fbdev/nvidia/nv_setup.c
diff --git a/drivers/video/nvidia/nv_type.h b/drivers/video/fbdev/nvidia/nv_type.h
index c03f7f55c76d..c03f7f55c76d 100644
--- a/drivers/video/nvidia/nv_type.h
+++ b/drivers/video/fbdev/nvidia/nv_type.h
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/fbdev/nvidia/nvidia.c
index def041204676..def041204676 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/fbdev/nvidia/nvidia.c
diff --git a/drivers/video/ocfb.c b/drivers/video/fbdev/ocfb.c
index 7f9dc9bec309..7f9dc9bec309 100644
--- a/drivers/video/ocfb.c
+++ b/drivers/video/fbdev/ocfb.c
diff --git a/drivers/video/offb.c b/drivers/video/fbdev/offb.c
index 7d44d669d5b6..7d44d669d5b6 100644
--- a/drivers/video/offb.c
+++ b/drivers/video/fbdev/offb.c
diff --git a/drivers/video/omap/Kconfig b/drivers/video/fbdev/omap/Kconfig
index 0bc3a936ce2b..0bc3a936ce2b 100644
--- a/drivers/video/omap/Kconfig
+++ b/drivers/video/fbdev/omap/Kconfig
diff --git a/drivers/video/omap/Makefile b/drivers/video/fbdev/omap/Makefile
index 1927faffb5bc..1927faffb5bc 100644
--- a/drivers/video/omap/Makefile
+++ b/drivers/video/fbdev/omap/Makefile
diff --git a/drivers/video/omap/hwa742.c b/drivers/video/fbdev/omap/hwa742.c
index a4ee65b8f918..a4ee65b8f918 100644
--- a/drivers/video/omap/hwa742.c
+++ b/drivers/video/fbdev/omap/hwa742.c
diff --git a/drivers/video/omap/lcd_ams_delta.c b/drivers/video/fbdev/omap/lcd_ams_delta.c
index 4a5f2cd3d3bf..4a5f2cd3d3bf 100644
--- a/drivers/video/omap/lcd_ams_delta.c
+++ b/drivers/video/fbdev/omap/lcd_ams_delta.c
diff --git a/drivers/video/omap/lcd_h3.c b/drivers/video/fbdev/omap/lcd_h3.c
index 49bdeca81e50..49bdeca81e50 100644
--- a/drivers/video/omap/lcd_h3.c
+++ b/drivers/video/fbdev/omap/lcd_h3.c
diff --git a/drivers/video/omap/lcd_htcherald.c b/drivers/video/fbdev/omap/lcd_htcherald.c
index 20f477851d54..20f477851d54 100644
--- a/drivers/video/omap/lcd_htcherald.c
+++ b/drivers/video/fbdev/omap/lcd_htcherald.c
diff --git a/drivers/video/omap/lcd_inn1510.c b/drivers/video/fbdev/omap/lcd_inn1510.c
index 2ee423279e35..2ee423279e35 100644
--- a/drivers/video/omap/lcd_inn1510.c
+++ b/drivers/video/fbdev/omap/lcd_inn1510.c
diff --git a/drivers/video/omap/lcd_inn1610.c b/drivers/video/fbdev/omap/lcd_inn1610.c
index e3d3d135aa48..e3d3d135aa48 100644
--- a/drivers/video/omap/lcd_inn1610.c
+++ b/drivers/video/fbdev/omap/lcd_inn1610.c
diff --git a/drivers/video/omap/lcd_mipid.c b/drivers/video/fbdev/omap/lcd_mipid.c
index 803fee618d57..803fee618d57 100644
--- a/drivers/video/omap/lcd_mipid.c
+++ b/drivers/video/fbdev/omap/lcd_mipid.c
diff --git a/drivers/video/omap/lcd_osk.c b/drivers/video/fbdev/omap/lcd_osk.c
index 7fbe04bce0ed..7fbe04bce0ed 100644
--- a/drivers/video/omap/lcd_osk.c
+++ b/drivers/video/fbdev/omap/lcd_osk.c
diff --git a/drivers/video/omap/lcd_palmte.c b/drivers/video/fbdev/omap/lcd_palmte.c
index ff4fb624b904..ff4fb624b904 100644
--- a/drivers/video/omap/lcd_palmte.c
+++ b/drivers/video/fbdev/omap/lcd_palmte.c
diff --git a/drivers/video/omap/lcd_palmtt.c b/drivers/video/fbdev/omap/lcd_palmtt.c
index aaf3c8ba1243..aaf3c8ba1243 100644
--- a/drivers/video/omap/lcd_palmtt.c
+++ b/drivers/video/fbdev/omap/lcd_palmtt.c
diff --git a/drivers/video/omap/lcd_palmz71.c b/drivers/video/fbdev/omap/lcd_palmz71.c
index 3b7d8aa1cf34..3b7d8aa1cf34 100644
--- a/drivers/video/omap/lcd_palmz71.c
+++ b/drivers/video/fbdev/omap/lcd_palmz71.c
diff --git a/drivers/video/omap/lcdc.c b/drivers/video/fbdev/omap/lcdc.c
index b52f62595f65..b52f62595f65 100644
--- a/drivers/video/omap/lcdc.c
+++ b/drivers/video/fbdev/omap/lcdc.c
diff --git a/drivers/video/omap/lcdc.h b/drivers/video/fbdev/omap/lcdc.h
index 845222270db3..845222270db3 100644
--- a/drivers/video/omap/lcdc.h
+++ b/drivers/video/fbdev/omap/lcdc.h
diff --git a/drivers/video/omap/omapfb.h b/drivers/video/fbdev/omap/omapfb.h
index 2921d20e4fba..2921d20e4fba 100644
--- a/drivers/video/omap/omapfb.h
+++ b/drivers/video/fbdev/omap/omapfb.h
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/fbdev/omap/omapfb_main.c
index e4fc6d9b5371..e4fc6d9b5371 100644
--- a/drivers/video/omap/omapfb_main.c
+++ b/drivers/video/fbdev/omap/omapfb_main.c
diff --git a/drivers/video/omap/sossi.c b/drivers/video/fbdev/omap/sossi.c
index d4e7684e7045..d4e7684e7045 100644
--- a/drivers/video/omap/sossi.c
+++ b/drivers/video/fbdev/omap/sossi.c
diff --git a/drivers/video/fbdev/omap2/Kconfig b/drivers/video/fbdev/omap2/Kconfig
new file mode 100644
index 000000000000..c22955d2de9a
--- /dev/null
+++ b/drivers/video/fbdev/omap2/Kconfig
@@ -0,0 +1,10 @@
+config OMAP2_VRFB
+ bool
+
+if ARCH_OMAP2PLUS
+
+source "drivers/video/fbdev/omap2/dss/Kconfig"
+source "drivers/video/fbdev/omap2/omapfb/Kconfig"
+source "drivers/video/fbdev/omap2/displays-new/Kconfig"
+
+endif
diff --git a/drivers/video/omap2/Makefile b/drivers/video/fbdev/omap2/Makefile
index bf8127df8c71..bf8127df8c71 100644
--- a/drivers/video/omap2/Makefile
+++ b/drivers/video/fbdev/omap2/Makefile
diff --git a/drivers/video/omap2/displays-new/Kconfig b/drivers/video/fbdev/omap2/displays-new/Kconfig
index e6cfc38160d3..e6cfc38160d3 100644
--- a/drivers/video/omap2/displays-new/Kconfig
+++ b/drivers/video/fbdev/omap2/displays-new/Kconfig
diff --git a/drivers/video/omap2/displays-new/Makefile b/drivers/video/fbdev/omap2/displays-new/Makefile
index 0323a8a1c682..0323a8a1c682 100644
--- a/drivers/video/omap2/displays-new/Makefile
+++ b/drivers/video/fbdev/omap2/displays-new/Makefile
diff --git a/drivers/video/omap2/displays-new/connector-analog-tv.c b/drivers/video/fbdev/omap2/displays-new/connector-analog-tv.c
index 5ee3b5505f7f..5ee3b5505f7f 100644
--- a/drivers/video/omap2/displays-new/connector-analog-tv.c
+++ b/drivers/video/fbdev/omap2/displays-new/connector-analog-tv.c
diff --git a/drivers/video/omap2/displays-new/connector-dvi.c b/drivers/video/fbdev/omap2/displays-new/connector-dvi.c
index 74de2bc50c4f..74de2bc50c4f 100644
--- a/drivers/video/omap2/displays-new/connector-dvi.c
+++ b/drivers/video/fbdev/omap2/displays-new/connector-dvi.c
diff --git a/drivers/video/omap2/displays-new/connector-hdmi.c b/drivers/video/fbdev/omap2/displays-new/connector-hdmi.c
index 29ed21b9dce5..29ed21b9dce5 100644
--- a/drivers/video/omap2/displays-new/connector-hdmi.c
+++ b/drivers/video/fbdev/omap2/displays-new/connector-hdmi.c
diff --git a/drivers/video/omap2/displays-new/encoder-tfp410.c b/drivers/video/fbdev/omap2/displays-new/encoder-tfp410.c
index b4e9a42a79e6..b4e9a42a79e6 100644
--- a/drivers/video/omap2/displays-new/encoder-tfp410.c
+++ b/drivers/video/fbdev/omap2/displays-new/encoder-tfp410.c
diff --git a/drivers/video/omap2/displays-new/encoder-tpd12s015.c b/drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c
index 7e33686171e3..7e33686171e3 100644
--- a/drivers/video/omap2/displays-new/encoder-tpd12s015.c
+++ b/drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c
diff --git a/drivers/video/omap2/displays-new/panel-dpi.c b/drivers/video/fbdev/omap2/displays-new/panel-dpi.c
index 5f8f7e7c81ef..5f8f7e7c81ef 100644
--- a/drivers/video/omap2/displays-new/panel-dpi.c
+++ b/drivers/video/fbdev/omap2/displays-new/panel-dpi.c
diff --git a/drivers/video/omap2/displays-new/panel-dsi-cm.c b/drivers/video/fbdev/omap2/displays-new/panel-dsi-cm.c
index d6f14e8717e8..d6f14e8717e8 100644
--- a/drivers/video/omap2/displays-new/panel-dsi-cm.c
+++ b/drivers/video/fbdev/omap2/displays-new/panel-dsi-cm.c
diff --git a/drivers/video/omap2/displays-new/panel-lgphilips-lb035q02.c b/drivers/video/fbdev/omap2/displays-new/panel-lgphilips-lb035q02.c
index 2e6b513222d9..2e6b513222d9 100644
--- a/drivers/video/omap2/displays-new/panel-lgphilips-lb035q02.c
+++ b/drivers/video/fbdev/omap2/displays-new/panel-lgphilips-lb035q02.c
diff --git a/drivers/video/omap2/displays-new/panel-nec-nl8048hl11.c b/drivers/video/fbdev/omap2/displays-new/panel-nec-nl8048hl11.c
index 996fa004b48c..996fa004b48c 100644
--- a/drivers/video/omap2/displays-new/panel-nec-nl8048hl11.c
+++ b/drivers/video/fbdev/omap2/displays-new/panel-nec-nl8048hl11.c
diff --git a/drivers/video/omap2/displays-new/panel-sharp-ls037v7dw01.c b/drivers/video/fbdev/omap2/displays-new/panel-sharp-ls037v7dw01.c
index b2f710be565d..b2f710be565d 100644
--- a/drivers/video/omap2/displays-new/panel-sharp-ls037v7dw01.c
+++ b/drivers/video/fbdev/omap2/displays-new/panel-sharp-ls037v7dw01.c
diff --git a/drivers/video/omap2/displays-new/panel-sony-acx565akm.c b/drivers/video/fbdev/omap2/displays-new/panel-sony-acx565akm.c
index c7ba4d8b928a..c7ba4d8b928a 100644
--- a/drivers/video/omap2/displays-new/panel-sony-acx565akm.c
+++ b/drivers/video/fbdev/omap2/displays-new/panel-sony-acx565akm.c
diff --git a/drivers/video/omap2/displays-new/panel-tpo-td028ttec1.c b/drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c
index fae6adc005a7..fae6adc005a7 100644
--- a/drivers/video/omap2/displays-new/panel-tpo-td028ttec1.c
+++ b/drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c
diff --git a/drivers/video/omap2/displays-new/panel-tpo-td043mtea1.c b/drivers/video/fbdev/omap2/displays-new/panel-tpo-td043mtea1.c
index 875b40263b33..875b40263b33 100644
--- a/drivers/video/omap2/displays-new/panel-tpo-td043mtea1.c
+++ b/drivers/video/fbdev/omap2/displays-new/panel-tpo-td043mtea1.c
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/fbdev/omap2/dss/Kconfig
index dde4281663b1..dde4281663b1 100644
--- a/drivers/video/omap2/dss/Kconfig
+++ b/drivers/video/fbdev/omap2/dss/Kconfig
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/fbdev/omap2/dss/Makefile
index 8aec8bda27cc..8aec8bda27cc 100644
--- a/drivers/video/omap2/dss/Makefile
+++ b/drivers/video/fbdev/omap2/dss/Makefile
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/fbdev/omap2/dss/apply.c
index 0a0b084ce65d..0a0b084ce65d 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/fbdev/omap2/dss/apply.c
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/fbdev/omap2/dss/core.c
index ffa45c894cd4..ffa45c894cd4 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/fbdev/omap2/dss/core.c
diff --git a/drivers/video/omap2/dss/dispc-compat.c b/drivers/video/fbdev/omap2/dss/dispc-compat.c
index 83779c2b292a..83779c2b292a 100644
--- a/drivers/video/omap2/dss/dispc-compat.c
+++ b/drivers/video/fbdev/omap2/dss/dispc-compat.c
diff --git a/drivers/video/omap2/dss/dispc-compat.h b/drivers/video/fbdev/omap2/dss/dispc-compat.h
index 14a69b3d4fb0..14a69b3d4fb0 100644
--- a/drivers/video/omap2/dss/dispc-compat.h
+++ b/drivers/video/fbdev/omap2/dss/dispc-compat.h
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/fbdev/omap2/dss/dispc.c
index 2bbdb7ff7daf..f18397c33e8f 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/fbdev/omap2/dss/dispc.c
@@ -101,6 +101,8 @@ static struct {
void __iomem *base;
int irq;
+ irq_handler_t user_handler;
+ void *user_data;
unsigned long core_clk_rate;
unsigned long tv_pclk_rate;
@@ -113,6 +115,8 @@ static struct {
u32 ctx[DISPC_SZ_REGS / sizeof(u32)];
const struct dispc_features *feat;
+
+ bool is_enabled;
} dispc;
enum omap_color_component {
@@ -141,12 +145,18 @@ enum mgr_reg_fields {
DISPC_MGR_FLD_NUM,
};
+struct dispc_reg_field {
+ u16 reg;
+ u8 high;
+ u8 low;
+};
+
static const struct {
const char *name;
u32 vsync_irq;
u32 framedone_irq;
u32 sync_lost_irq;
- struct reg_field reg_desc[DISPC_MGR_FLD_NUM];
+ struct dispc_reg_field reg_desc[DISPC_MGR_FLD_NUM];
} mgr_desc[] = {
[OMAP_DSS_CHANNEL_LCD] = {
.name = "LCD",
@@ -238,13 +248,13 @@ static inline u32 dispc_read_reg(const u16 idx)
static u32 mgr_fld_read(enum omap_channel channel, enum mgr_reg_fields regfld)
{
- const struct reg_field rfld = mgr_desc[channel].reg_desc[regfld];
+ const struct dispc_reg_field rfld = mgr_desc[channel].reg_desc[regfld];
return REG_GET(rfld.reg, rfld.high, rfld.low);
}
static void mgr_fld_write(enum omap_channel channel,
enum mgr_reg_fields regfld, int val) {
- const struct reg_field rfld = mgr_desc[channel].reg_desc[regfld];
+ const struct dispc_reg_field rfld = mgr_desc[channel].reg_desc[regfld];
REG_FLD_MOD(rfld.reg, val, rfld.high, rfld.low);
}
@@ -3669,16 +3679,44 @@ static int __init dispc_init_features(struct platform_device *pdev)
return 0;
}
+static irqreturn_t dispc_irq_handler(int irq, void *arg)
+{
+ if (!dispc.is_enabled)
+ return IRQ_NONE;
+
+ return dispc.user_handler(irq, dispc.user_data);
+}
+
int dispc_request_irq(irq_handler_t handler, void *dev_id)
{
- return devm_request_irq(&dispc.pdev->dev, dispc.irq, handler,
- IRQF_SHARED, "OMAP DISPC", dev_id);
+ int r;
+
+ if (dispc.user_handler != NULL)
+ return -EBUSY;
+
+ dispc.user_handler = handler;
+ dispc.user_data = dev_id;
+
+ /* ensure the dispc_irq_handler sees the values above */
+ smp_wmb();
+
+ r = devm_request_irq(&dispc.pdev->dev, dispc.irq, dispc_irq_handler,
+ IRQF_SHARED, "OMAP DISPC", &dispc);
+ if (r) {
+ dispc.user_handler = NULL;
+ dispc.user_data = NULL;
+ }
+
+ return r;
}
EXPORT_SYMBOL(dispc_request_irq);
void dispc_free_irq(void *dev_id)
{
- devm_free_irq(&dispc.pdev->dev, dispc.irq, dev_id);
+ devm_free_irq(&dispc.pdev->dev, dispc.irq, &dispc);
+
+ dispc.user_handler = NULL;
+ dispc.user_data = NULL;
}
EXPORT_SYMBOL(dispc_free_irq);
@@ -3750,6 +3788,12 @@ static int __exit omap_dispchw_remove(struct platform_device *pdev)
static int dispc_runtime_suspend(struct device *dev)
{
+ dispc.is_enabled = false;
+ /* ensure the dispc_irq_handler sees the is_enabled value */
+ smp_wmb();
+ /* wait for current handler to finish before turning the DISPC off */
+ synchronize_irq(dispc.irq);
+
dispc_save_context();
return 0;
@@ -3763,12 +3807,15 @@ static int dispc_runtime_resume(struct device *dev)
* _omap_dispc_initial_config(). We can thus use it to detect if
* we have lost register context.
*/
- if (REG_GET(DISPC_CONFIG, 2, 1) == OMAP_DSS_LOAD_FRAME_ONLY)
- return 0;
+ if (REG_GET(DISPC_CONFIG, 2, 1) != OMAP_DSS_LOAD_FRAME_ONLY) {
+ _omap_dispc_initial_config();
- _omap_dispc_initial_config();
+ dispc_restore_context();
+ }
- dispc_restore_context();
+ dispc.is_enabled = true;
+ /* ensure the dispc_irq_handler sees the is_enabled value */
+ smp_wmb();
return 0;
}
diff --git a/drivers/video/omap2/dss/dispc.h b/drivers/video/fbdev/omap2/dss/dispc.h
index 78edb449c763..78edb449c763 100644
--- a/drivers/video/omap2/dss/dispc.h
+++ b/drivers/video/fbdev/omap2/dss/dispc.h
diff --git a/drivers/video/omap2/dss/dispc_coefs.c b/drivers/video/fbdev/omap2/dss/dispc_coefs.c
index 038c15b04215..038c15b04215 100644
--- a/drivers/video/omap2/dss/dispc_coefs.c
+++ b/drivers/video/fbdev/omap2/dss/dispc_coefs.c
diff --git a/drivers/video/omap2/dss/display-sysfs.c b/drivers/video/fbdev/omap2/dss/display-sysfs.c
index 5a2095a98ed8..5a2095a98ed8 100644
--- a/drivers/video/omap2/dss/display-sysfs.c
+++ b/drivers/video/fbdev/omap2/dss/display-sysfs.c
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/fbdev/omap2/dss/display.c
index 2412a0dd0c13..2412a0dd0c13 100644
--- a/drivers/video/omap2/dss/display.c
+++ b/drivers/video/fbdev/omap2/dss/display.c
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/fbdev/omap2/dss/dpi.c
index 157921db447a..157921db447a 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/fbdev/omap2/dss/dpi.c
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/fbdev/omap2/dss/dsi.c
index 121d1049d0bc..8be9b04d8849 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/fbdev/omap2/dss/dsi.c
@@ -297,6 +297,8 @@ struct dsi_data {
int irq;
+ bool is_enabled;
+
struct clk *dss_clk;
struct clk *sys_clk;
@@ -795,6 +797,9 @@ static irqreturn_t omap_dsi_irq_handler(int irq, void *arg)
dsidev = (struct platform_device *) arg;
dsi = dsi_get_dsidrv_data(dsidev);
+ if (!dsi->is_enabled)
+ return IRQ_NONE;
+
spin_lock(&dsi->irq_lock);
irqstatus = dsi_read_reg(dsidev, DSI_IRQSTATUS);
@@ -5671,6 +5676,15 @@ static int __exit omap_dsihw_remove(struct platform_device *dsidev)
static int dsi_runtime_suspend(struct device *dev)
{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct dsi_data *dsi = dsi_get_dsidrv_data(pdev);
+
+ dsi->is_enabled = false;
+ /* ensure the irq handler sees the is_enabled value */
+ smp_wmb();
+ /* wait for current handler to finish before turning the DSI off */
+ synchronize_irq(dsi->irq);
+
dispc_runtime_put();
return 0;
@@ -5678,12 +5692,18 @@ static int dsi_runtime_suspend(struct device *dev)
static int dsi_runtime_resume(struct device *dev)
{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct dsi_data *dsi = dsi_get_dsidrv_data(pdev);
int r;
r = dispc_runtime_get();
if (r)
return r;
+ dsi->is_enabled = true;
+ /* ensure the irq handler sees the is_enabled value */
+ smp_wmb();
+
return 0;
}
diff --git a/drivers/video/omap2/dss/dss-of.c b/drivers/video/fbdev/omap2/dss/dss-of.c
index a4b20aaf6142..a4b20aaf6142 100644
--- a/drivers/video/omap2/dss/dss-of.c
+++ b/drivers/video/fbdev/omap2/dss/dss-of.c
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/fbdev/omap2/dss/dss.c
index 825c019ddee7..d55266c0e029 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/fbdev/omap2/dss/dss.c
@@ -457,7 +457,7 @@ bool dss_div_calc(unsigned long pck, unsigned long fck_min,
fckd_stop = max(DIV_ROUND_UP(prate * m, fck_hw_max), 1ul);
for (fckd = fckd_start; fckd >= fckd_stop; --fckd) {
- fck = prate / fckd * m;
+ fck = DIV_ROUND_UP(prate, fckd) * m;
if (func(fck, data))
return true;
@@ -506,7 +506,7 @@ static int dss_setup_default_clock(void)
fck_div = DIV_ROUND_UP(prate * dss.feat->dss_fck_multiplier,
max_dss_fck);
- fck = prate / fck_div * dss.feat->dss_fck_multiplier;
+ fck = DIV_ROUND_UP(prate, fck_div) * dss.feat->dss_fck_multiplier;
}
r = dss_set_fck_rate(fck);
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/fbdev/omap2/dss/dss.h
index 918fec182424..560078fcb198 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/fbdev/omap2/dss/dss.h
@@ -131,12 +131,6 @@ struct dsi_clock_info {
u16 lp_clk_div;
};
-struct reg_field {
- u16 reg;
- u8 high;
- u8 low;
-};
-
struct dss_lcd_mgr_config {
enum dss_io_pad_mode io_pad_mode;
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/fbdev/omap2/dss/dss_features.c
index 7f8969191dc6..7f8969191dc6 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/fbdev/omap2/dss/dss_features.c
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/fbdev/omap2/dss/dss_features.h
index e3ef3b714896..e3ef3b714896 100644
--- a/drivers/video/omap2/dss/dss_features.h
+++ b/drivers/video/fbdev/omap2/dss/dss_features.h
diff --git a/drivers/video/omap2/dss/hdmi.h b/drivers/video/fbdev/omap2/dss/hdmi.h
index e25681ff5a70..e25681ff5a70 100644
--- a/drivers/video/omap2/dss/hdmi.h
+++ b/drivers/video/fbdev/omap2/dss/hdmi.h
diff --git a/drivers/video/omap2/dss/hdmi4.c b/drivers/video/fbdev/omap2/dss/hdmi4.c
index f5f7944a1fd1..f5f7944a1fd1 100644
--- a/drivers/video/omap2/dss/hdmi4.c
+++ b/drivers/video/fbdev/omap2/dss/hdmi4.c
diff --git a/drivers/video/omap2/dss/hdmi4_core.c b/drivers/video/fbdev/omap2/dss/hdmi4_core.c
index 2eb04dcf807c..2eb04dcf807c 100644
--- a/drivers/video/omap2/dss/hdmi4_core.c
+++ b/drivers/video/fbdev/omap2/dss/hdmi4_core.c
diff --git a/drivers/video/omap2/dss/hdmi4_core.h b/drivers/video/fbdev/omap2/dss/hdmi4_core.h
index bb646896fa82..bb646896fa82 100644
--- a/drivers/video/omap2/dss/hdmi4_core.h
+++ b/drivers/video/fbdev/omap2/dss/hdmi4_core.h
diff --git a/drivers/video/omap2/dss/hdmi_common.c b/drivers/video/fbdev/omap2/dss/hdmi_common.c
index b11afac8e068..0b12a3f62fe1 100644
--- a/drivers/video/omap2/dss/hdmi_common.c
+++ b/drivers/video/fbdev/omap2/dss/hdmi_common.c
@@ -347,17 +347,17 @@ int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts)
case 96000:
case 192000:
if (deep_color == 125)
- if (pclk == 27027 || pclk == 74250)
+ if (pclk == 27027000 || pclk == 74250000)
deep_color_correct = true;
if (deep_color == 150)
- if (pclk == 27027)
+ if (pclk == 27027000)
deep_color_correct = true;
break;
case 44100:
case 88200:
case 176400:
if (deep_color == 125)
- if (pclk == 27027)
+ if (pclk == 27027000)
deep_color_correct = true;
break;
default:
@@ -418,7 +418,7 @@ int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts)
}
}
/* Calculate CTS. See HDMI 1.3a or 1.4a specifications */
- *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10);
+ *cts = (pclk/1000) * (*n / 128) * deep_color / (sample_freq / 10);
return 0;
}
diff --git a/drivers/video/omap2/dss/hdmi_phy.c b/drivers/video/fbdev/omap2/dss/hdmi_phy.c
index dd376ce8da01..dd376ce8da01 100644
--- a/drivers/video/omap2/dss/hdmi_phy.c
+++ b/drivers/video/fbdev/omap2/dss/hdmi_phy.c
diff --git a/drivers/video/omap2/dss/hdmi_pll.c b/drivers/video/fbdev/omap2/dss/hdmi_pll.c
index 5fc71215c303..5fc71215c303 100644
--- a/drivers/video/omap2/dss/hdmi_pll.c
+++ b/drivers/video/fbdev/omap2/dss/hdmi_pll.c
diff --git a/drivers/video/omap2/dss/hdmi_wp.c b/drivers/video/fbdev/omap2/dss/hdmi_wp.c
index f5f4ccf50d90..f5f4ccf50d90 100644
--- a/drivers/video/omap2/dss/hdmi_wp.c
+++ b/drivers/video/fbdev/omap2/dss/hdmi_wp.c
diff --git a/drivers/video/omap2/dss/manager-sysfs.c b/drivers/video/fbdev/omap2/dss/manager-sysfs.c
index 37b59fe28dc8..37b59fe28dc8 100644
--- a/drivers/video/omap2/dss/manager-sysfs.c
+++ b/drivers/video/fbdev/omap2/dss/manager-sysfs.c
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/fbdev/omap2/dss/manager.c
index 1aac9b4191a9..1aac9b4191a9 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/fbdev/omap2/dss/manager.c
diff --git a/drivers/video/omap2/dss/output.c b/drivers/video/fbdev/omap2/dss/output.c
index 2ab3afa615e8..2ab3afa615e8 100644
--- a/drivers/video/omap2/dss/output.c
+++ b/drivers/video/fbdev/omap2/dss/output.c
diff --git a/drivers/video/omap2/dss/overlay-sysfs.c b/drivers/video/fbdev/omap2/dss/overlay-sysfs.c
index 4cc5ddebfb34..4cc5ddebfb34 100644
--- a/drivers/video/omap2/dss/overlay-sysfs.c
+++ b/drivers/video/fbdev/omap2/dss/overlay-sysfs.c
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/fbdev/omap2/dss/overlay.c
index 2f7cee985cdd..2f7cee985cdd 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/fbdev/omap2/dss/overlay.c
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/fbdev/omap2/dss/rfbi.c
index c8a81a2b879c..c8a81a2b879c 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/fbdev/omap2/dss/rfbi.c
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/fbdev/omap2/dss/sdi.c
index 911dcc9173a6..911dcc9173a6 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/fbdev/omap2/dss/sdi.c
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/fbdev/omap2/dss/venc.c
index 21d81113962b..21d81113962b 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/fbdev/omap2/dss/venc.c
diff --git a/drivers/video/omap2/dss/venc_panel.c b/drivers/video/fbdev/omap2/dss/venc_panel.c
index af68cd444d7e..af68cd444d7e 100644
--- a/drivers/video/omap2/dss/venc_panel.c
+++ b/drivers/video/fbdev/omap2/dss/venc_panel.c
diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/fbdev/omap2/omapfb/Kconfig
index 4cb12ce68855..4cb12ce68855 100644
--- a/drivers/video/omap2/omapfb/Kconfig
+++ b/drivers/video/fbdev/omap2/omapfb/Kconfig
diff --git a/drivers/video/omap2/omapfb/Makefile b/drivers/video/fbdev/omap2/omapfb/Makefile
index 51c2e00d9bf8..51c2e00d9bf8 100644
--- a/drivers/video/omap2/omapfb/Makefile
+++ b/drivers/video/fbdev/omap2/omapfb/Makefile
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c
index 146b6f5428db..146b6f5428db 100644
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/fbdev/omap2/omapfb/omapfb-main.c
index ec2d132c782d..ec2d132c782d 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/fbdev/omap2/omapfb/omapfb-main.c
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/fbdev/omap2/omapfb/omapfb-sysfs.c
index 18fa9e1d0033..18fa9e1d0033 100644
--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
+++ b/drivers/video/fbdev/omap2/omapfb/omapfb-sysfs.c
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/fbdev/omap2/omapfb/omapfb.h
index 623cd872a367..623cd872a367 100644
--- a/drivers/video/omap2/omapfb/omapfb.h
+++ b/drivers/video/fbdev/omap2/omapfb/omapfb.h
diff --git a/drivers/video/omap2/vrfb.c b/drivers/video/fbdev/omap2/vrfb.c
index f346b02eee1d..f346b02eee1d 100644
--- a/drivers/video/omap2/vrfb.c
+++ b/drivers/video/fbdev/omap2/vrfb.c
diff --git a/drivers/video/p9100.c b/drivers/video/fbdev/p9100.c
index 367cea8f43f3..367cea8f43f3 100644
--- a/drivers/video/p9100.c
+++ b/drivers/video/fbdev/p9100.c
diff --git a/drivers/video/platinumfb.c b/drivers/video/fbdev/platinumfb.c
index 4c9299576827..4c9299576827 100644
--- a/drivers/video/platinumfb.c
+++ b/drivers/video/fbdev/platinumfb.c
diff --git a/drivers/video/platinumfb.h b/drivers/video/fbdev/platinumfb.h
index f6bd77cafd17..f6bd77cafd17 100644
--- a/drivers/video/platinumfb.h
+++ b/drivers/video/fbdev/platinumfb.h
diff --git a/drivers/video/pm2fb.c b/drivers/video/fbdev/pm2fb.c
index 3b85b647bc10..3b85b647bc10 100644
--- a/drivers/video/pm2fb.c
+++ b/drivers/video/fbdev/pm2fb.c
diff --git a/drivers/video/pm3fb.c b/drivers/video/fbdev/pm3fb.c
index 4bf3273d0433..4bf3273d0433 100644
--- a/drivers/video/pm3fb.c
+++ b/drivers/video/fbdev/pm3fb.c
diff --git a/drivers/video/pmag-aa-fb.c b/drivers/video/fbdev/pmag-aa-fb.c
index 838424817de2..838424817de2 100644
--- a/drivers/video/pmag-aa-fb.c
+++ b/drivers/video/fbdev/pmag-aa-fb.c
diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/fbdev/pmag-ba-fb.c
index 914a52ba8477..914a52ba8477 100644
--- a/drivers/video/pmag-ba-fb.c
+++ b/drivers/video/fbdev/pmag-ba-fb.c
diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/fbdev/pmagb-b-fb.c
index 0822b6f8dddc..0822b6f8dddc 100644
--- a/drivers/video/pmagb-b-fb.c
+++ b/drivers/video/fbdev/pmagb-b-fb.c
diff --git a/drivers/video/ps3fb.c b/drivers/video/fbdev/ps3fb.c
index b269abd932aa..b269abd932aa 100644
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/fbdev/ps3fb.c
diff --git a/drivers/video/pvr2fb.c b/drivers/video/fbdev/pvr2fb.c
index 167cffff3d4e..167cffff3d4e 100644
--- a/drivers/video/pvr2fb.c
+++ b/drivers/video/fbdev/pvr2fb.c
diff --git a/drivers/video/pxa168fb.c b/drivers/video/fbdev/pxa168fb.c
index c95b9e46d48f..c95b9e46d48f 100644
--- a/drivers/video/pxa168fb.c
+++ b/drivers/video/fbdev/pxa168fb.c
diff --git a/drivers/video/pxa168fb.h b/drivers/video/fbdev/pxa168fb.h
index eee09279c524..eee09279c524 100644
--- a/drivers/video/pxa168fb.h
+++ b/drivers/video/fbdev/pxa168fb.h
diff --git a/drivers/video/pxa3xx-gcu.c b/drivers/video/fbdev/pxa3xx-gcu.c
index 417f9a27eb7d..417f9a27eb7d 100644
--- a/drivers/video/pxa3xx-gcu.c
+++ b/drivers/video/fbdev/pxa3xx-gcu.c
diff --git a/drivers/video/pxa3xx-gcu.h b/drivers/video/fbdev/pxa3xx-gcu.h
index 0428ed03dc49..0428ed03dc49 100644
--- a/drivers/video/pxa3xx-gcu.h
+++ b/drivers/video/fbdev/pxa3xx-gcu.h
diff --git a/drivers/video/pxafb.c b/drivers/video/fbdev/pxafb.c
index 1ecd9cec2921..1ecd9cec2921 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/fbdev/pxafb.c
diff --git a/drivers/video/pxafb.h b/drivers/video/fbdev/pxafb.h
index 26ba9fa3f737..26ba9fa3f737 100644
--- a/drivers/video/pxafb.h
+++ b/drivers/video/fbdev/pxafb.h
diff --git a/drivers/video/q40fb.c b/drivers/video/fbdev/q40fb.c
index 7487f76f6275..7487f76f6275 100644
--- a/drivers/video/q40fb.c
+++ b/drivers/video/fbdev/q40fb.c
diff --git a/drivers/video/riva/Makefile b/drivers/video/fbdev/riva/Makefile
index 8898c9915b02..8898c9915b02 100644
--- a/drivers/video/riva/Makefile
+++ b/drivers/video/fbdev/riva/Makefile
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/fbdev/riva/fbdev.c
index 8a8d7f060784..8a8d7f060784 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/fbdev/riva/fbdev.c
diff --git a/drivers/video/riva/nv_driver.c b/drivers/video/fbdev/riva/nv_driver.c
index f3694cf17e58..f3694cf17e58 100644
--- a/drivers/video/riva/nv_driver.c
+++ b/drivers/video/fbdev/riva/nv_driver.c
diff --git a/drivers/video/riva/nv_type.h b/drivers/video/fbdev/riva/nv_type.h
index a69480c9a67c..a69480c9a67c 100644
--- a/drivers/video/riva/nv_type.h
+++ b/drivers/video/fbdev/riva/nv_type.h
diff --git a/drivers/video/riva/nvreg.h b/drivers/video/fbdev/riva/nvreg.h
index abfc167ae8d8..abfc167ae8d8 100644
--- a/drivers/video/riva/nvreg.h
+++ b/drivers/video/fbdev/riva/nvreg.h
diff --git a/drivers/video/riva/riva_hw.c b/drivers/video/fbdev/riva/riva_hw.c
index 78fdbf5178d7..78fdbf5178d7 100644
--- a/drivers/video/riva/riva_hw.c
+++ b/drivers/video/fbdev/riva/riva_hw.c
diff --git a/drivers/video/riva/riva_hw.h b/drivers/video/fbdev/riva/riva_hw.h
index c2769f73e0b2..c2769f73e0b2 100644
--- a/drivers/video/riva/riva_hw.h
+++ b/drivers/video/fbdev/riva/riva_hw.h
diff --git a/drivers/video/riva/riva_tbl.h b/drivers/video/fbdev/riva/riva_tbl.h
index 7ee7d72932d4..7ee7d72932d4 100644
--- a/drivers/video/riva/riva_tbl.h
+++ b/drivers/video/fbdev/riva/riva_tbl.h
diff --git a/drivers/video/riva/rivafb-i2c.c b/drivers/video/fbdev/riva/rivafb-i2c.c
index 6a183375ced1..6a183375ced1 100644
--- a/drivers/video/riva/rivafb-i2c.c
+++ b/drivers/video/fbdev/riva/rivafb-i2c.c
diff --git a/drivers/video/riva/rivafb.h b/drivers/video/fbdev/riva/rivafb.h
index d9f107b704c6..d9f107b704c6 100644
--- a/drivers/video/riva/rivafb.h
+++ b/drivers/video/fbdev/riva/rivafb.h
diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/fbdev/s1d13xxxfb.c
index 83433cb0dfba..83433cb0dfba 100644
--- a/drivers/video/s1d13xxxfb.c
+++ b/drivers/video/fbdev/s1d13xxxfb.c
diff --git a/drivers/video/s3c-fb.c b/drivers/video/fbdev/s3c-fb.c
index 62acae2694a9..62acae2694a9 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/fbdev/s3c-fb.c
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/fbdev/s3c2410fb.c
index 81af5a63e9e1..81af5a63e9e1 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/fbdev/s3c2410fb.c
diff --git a/drivers/video/s3c2410fb.h b/drivers/video/fbdev/s3c2410fb.h
index 47a17bd23011..47a17bd23011 100644
--- a/drivers/video/s3c2410fb.h
+++ b/drivers/video/fbdev/s3c2410fb.h
diff --git a/drivers/video/s3fb.c b/drivers/video/fbdev/s3fb.c
index 9a3f8f1c6aab..9a3f8f1c6aab 100644
--- a/drivers/video/s3fb.c
+++ b/drivers/video/fbdev/s3fb.c
diff --git a/drivers/video/sa1100fb.c b/drivers/video/fbdev/sa1100fb.c
index 580c444ec301..580c444ec301 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/fbdev/sa1100fb.c
diff --git a/drivers/video/sa1100fb.h b/drivers/video/fbdev/sa1100fb.h
index fc5d4292fad6..fc5d4292fad6 100644
--- a/drivers/video/sa1100fb.h
+++ b/drivers/video/fbdev/sa1100fb.h
diff --git a/drivers/video/savage/Makefile b/drivers/video/fbdev/savage/Makefile
index e09770fff8ea..e09770fff8ea 100644
--- a/drivers/video/savage/Makefile
+++ b/drivers/video/fbdev/savage/Makefile
diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/fbdev/savage/savagefb-i2c.c
index 80fa87e2ae2f..80fa87e2ae2f 100644
--- a/drivers/video/savage/savagefb-i2c.c
+++ b/drivers/video/fbdev/savage/savagefb-i2c.c
diff --git a/drivers/video/savage/savagefb.h b/drivers/video/fbdev/savage/savagefb.h
index dcaab9012ca2..dcaab9012ca2 100644
--- a/drivers/video/savage/savagefb.h
+++ b/drivers/video/fbdev/savage/savagefb.h
diff --git a/drivers/video/savage/savagefb_accel.c b/drivers/video/fbdev/savage/savagefb_accel.c
index bfefa6234cf0..bfefa6234cf0 100644
--- a/drivers/video/savage/savagefb_accel.c
+++ b/drivers/video/fbdev/savage/savagefb_accel.c
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/fbdev/savage/savagefb_driver.c
index 4dbf45f3b21a..4dbf45f3b21a 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/fbdev/savage/savagefb_driver.c
diff --git a/drivers/video/sbuslib.c b/drivers/video/fbdev/sbuslib.c
index a350209ffbd3..a350209ffbd3 100644
--- a/drivers/video/sbuslib.c
+++ b/drivers/video/fbdev/sbuslib.c
diff --git a/drivers/video/sbuslib.h b/drivers/video/fbdev/sbuslib.h
index 7ba3250236bd..7ba3250236bd 100644
--- a/drivers/video/sbuslib.h
+++ b/drivers/video/fbdev/sbuslib.h
diff --git a/drivers/video/sh7760fb.c b/drivers/video/fbdev/sh7760fb.c
index 1265b25f9f99..1265b25f9f99 100644
--- a/drivers/video/sh7760fb.c
+++ b/drivers/video/fbdev/sh7760fb.c
diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/fbdev/sh_mipi_dsi.c
index 8f6e8ff620d4..8f6e8ff620d4 100644
--- a/drivers/video/sh_mipi_dsi.c
+++ b/drivers/video/fbdev/sh_mipi_dsi.c
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/fbdev/sh_mobile_hdmi.c
index 9a33ee0413fb..9a33ee0413fb 100644
--- a/drivers/video/sh_mobile_hdmi.c
+++ b/drivers/video/fbdev/sh_mobile_hdmi.c
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/fbdev/sh_mobile_lcdcfb.c
index 2bcc84ac18c7..2bcc84ac18c7 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/fbdev/sh_mobile_lcdcfb.c
diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/fbdev/sh_mobile_lcdcfb.h
index f839adef1d90..f839adef1d90 100644
--- a/drivers/video/sh_mobile_lcdcfb.h
+++ b/drivers/video/fbdev/sh_mobile_lcdcfb.h
diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/fbdev/sh_mobile_meram.c
index a297de5cc859..a297de5cc859 100644
--- a/drivers/video/sh_mobile_meram.c
+++ b/drivers/video/fbdev/sh_mobile_meram.c
diff --git a/drivers/video/simplefb.c b/drivers/video/fbdev/simplefb.c
index 210f3a02121a..210f3a02121a 100644
--- a/drivers/video/simplefb.c
+++ b/drivers/video/fbdev/simplefb.c
diff --git a/drivers/video/sis/300vtbl.h b/drivers/video/fbdev/sis/300vtbl.h
index e4b4a2626da4..e4b4a2626da4 100644
--- a/drivers/video/sis/300vtbl.h
+++ b/drivers/video/fbdev/sis/300vtbl.h
diff --git a/drivers/video/sis/310vtbl.h b/drivers/video/fbdev/sis/310vtbl.h
index 54fcbbf4ef63..54fcbbf4ef63 100644
--- a/drivers/video/sis/310vtbl.h
+++ b/drivers/video/fbdev/sis/310vtbl.h
diff --git a/drivers/video/sis/Makefile b/drivers/video/fbdev/sis/Makefile
index f7c0046e5b1d..f7c0046e5b1d 100644
--- a/drivers/video/sis/Makefile
+++ b/drivers/video/fbdev/sis/Makefile
diff --git a/drivers/video/sis/init.c b/drivers/video/fbdev/sis/init.c
index bd40f5ecd901..bd40f5ecd901 100644
--- a/drivers/video/sis/init.c
+++ b/drivers/video/fbdev/sis/init.c
diff --git a/drivers/video/sis/init.h b/drivers/video/fbdev/sis/init.h
index 85d6738b6c64..85d6738b6c64 100644
--- a/drivers/video/sis/init.h
+++ b/drivers/video/fbdev/sis/init.h
diff --git a/drivers/video/sis/init301.c b/drivers/video/fbdev/sis/init301.c
index a89e3cafd5ad..a89e3cafd5ad 100644
--- a/drivers/video/sis/init301.c
+++ b/drivers/video/fbdev/sis/init301.c
diff --git a/drivers/video/sis/init301.h b/drivers/video/fbdev/sis/init301.h
index 2112d6d7feda..2112d6d7feda 100644
--- a/drivers/video/sis/init301.h
+++ b/drivers/video/fbdev/sis/init301.h
diff --git a/drivers/video/sis/initdef.h b/drivers/video/fbdev/sis/initdef.h
index 264b55a5947b..264b55a5947b 100644
--- a/drivers/video/sis/initdef.h
+++ b/drivers/video/fbdev/sis/initdef.h
diff --git a/drivers/video/sis/initextlfb.c b/drivers/video/fbdev/sis/initextlfb.c
index 3ab18f5a3759..3ab18f5a3759 100644
--- a/drivers/video/sis/initextlfb.c
+++ b/drivers/video/fbdev/sis/initextlfb.c
diff --git a/drivers/video/sis/oem300.h b/drivers/video/fbdev/sis/oem300.h
index b73f26840143..b73f26840143 100644
--- a/drivers/video/sis/oem300.h
+++ b/drivers/video/fbdev/sis/oem300.h
diff --git a/drivers/video/sis/oem310.h b/drivers/video/fbdev/sis/oem310.h
index 8fce56e4482c..8fce56e4482c 100644
--- a/drivers/video/sis/oem310.h
+++ b/drivers/video/fbdev/sis/oem310.h
diff --git a/drivers/video/sis/sis.h b/drivers/video/fbdev/sis/sis.h
index 1987f1b7212f..1987f1b7212f 100644
--- a/drivers/video/sis/sis.h
+++ b/drivers/video/fbdev/sis/sis.h
diff --git a/drivers/video/sis/sis_accel.c b/drivers/video/fbdev/sis/sis_accel.c
index ceb434c95c0d..ceb434c95c0d 100644
--- a/drivers/video/sis/sis_accel.c
+++ b/drivers/video/fbdev/sis/sis_accel.c
diff --git a/drivers/video/sis/sis_accel.h b/drivers/video/fbdev/sis/sis_accel.h
index 30e03cdf6b85..30e03cdf6b85 100644
--- a/drivers/video/sis/sis_accel.h
+++ b/drivers/video/fbdev/sis/sis_accel.h
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/fbdev/sis/sis_main.c
index 22ad028bf123..22ad028bf123 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/fbdev/sis/sis_main.c
diff --git a/drivers/video/sis/sis_main.h b/drivers/video/fbdev/sis/sis_main.h
index 32e23c209430..32e23c209430 100644
--- a/drivers/video/sis/sis_main.h
+++ b/drivers/video/fbdev/sis/sis_main.h
diff --git a/drivers/video/sis/vgatypes.h b/drivers/video/fbdev/sis/vgatypes.h
index e3f9976cfef0..e3f9976cfef0 100644
--- a/drivers/video/sis/vgatypes.h
+++ b/drivers/video/fbdev/sis/vgatypes.h
diff --git a/drivers/video/sis/vstruct.h b/drivers/video/fbdev/sis/vstruct.h
index ea94d214dcff..ea94d214dcff 100644
--- a/drivers/video/sis/vstruct.h
+++ b/drivers/video/fbdev/sis/vstruct.h
diff --git a/drivers/video/skeletonfb.c b/drivers/video/fbdev/skeletonfb.c
index fefde7c6add7..fefde7c6add7 100644
--- a/drivers/video/skeletonfb.c
+++ b/drivers/video/fbdev/skeletonfb.c
diff --git a/drivers/video/sm501fb.c b/drivers/video/fbdev/sm501fb.c
index 1501979099dc..1501979099dc 100644
--- a/drivers/video/sm501fb.c
+++ b/drivers/video/fbdev/sm501fb.c
diff --git a/drivers/video/smscufx.c b/drivers/video/fbdev/smscufx.c
index d513ed6a49f2..d513ed6a49f2 100644
--- a/drivers/video/smscufx.c
+++ b/drivers/video/fbdev/smscufx.c
diff --git a/drivers/video/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index f4daa59f0a80..f4daa59f0a80 100644
--- a/drivers/video/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
diff --git a/drivers/video/sstfb.c b/drivers/video/fbdev/sstfb.c
index f0cb279ef333..f0cb279ef333 100644
--- a/drivers/video/sstfb.c
+++ b/drivers/video/fbdev/sstfb.c
diff --git a/drivers/video/sticore.h b/drivers/video/fbdev/sticore.h
index af1619536ac8..af1619536ac8 100644
--- a/drivers/video/sticore.h
+++ b/drivers/video/fbdev/sticore.h
diff --git a/drivers/video/stifb.c b/drivers/video/fbdev/stifb.c
index cfe8a2f905c5..cfe8a2f905c5 100644
--- a/drivers/video/stifb.c
+++ b/drivers/video/fbdev/stifb.c
diff --git a/drivers/video/sunxvr1000.c b/drivers/video/fbdev/sunxvr1000.c
index 58241b47a96d..58241b47a96d 100644
--- a/drivers/video/sunxvr1000.c
+++ b/drivers/video/fbdev/sunxvr1000.c
diff --git a/drivers/video/sunxvr2500.c b/drivers/video/fbdev/sunxvr2500.c
index 843b6bab0483..843b6bab0483 100644
--- a/drivers/video/sunxvr2500.c
+++ b/drivers/video/fbdev/sunxvr2500.c
diff --git a/drivers/video/sunxvr500.c b/drivers/video/fbdev/sunxvr500.c
index 387350d004df..387350d004df 100644
--- a/drivers/video/sunxvr500.c
+++ b/drivers/video/fbdev/sunxvr500.c
diff --git a/drivers/video/tcx.c b/drivers/video/fbdev/tcx.c
index 7fb2d696fac7..7fb2d696fac7 100644
--- a/drivers/video/tcx.c
+++ b/drivers/video/fbdev/tcx.c
diff --git a/drivers/video/tdfxfb.c b/drivers/video/fbdev/tdfxfb.c
index f761fe375f5b..f761fe375f5b 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/fbdev/tdfxfb.c
diff --git a/drivers/video/tgafb.c b/drivers/video/fbdev/tgafb.c
index 65ba9921506e..65ba9921506e 100644
--- a/drivers/video/tgafb.c
+++ b/drivers/video/fbdev/tgafb.c
diff --git a/drivers/video/tmiofb.c b/drivers/video/fbdev/tmiofb.c
index 7fb4e321a431..7fb4e321a431 100644
--- a/drivers/video/tmiofb.c
+++ b/drivers/video/fbdev/tmiofb.c
diff --git a/drivers/video/tridentfb.c b/drivers/video/fbdev/tridentfb.c
index 7ed9a227f5ea..7ed9a227f5ea 100644
--- a/drivers/video/tridentfb.c
+++ b/drivers/video/fbdev/tridentfb.c
diff --git a/drivers/video/udlfb.c b/drivers/video/fbdev/udlfb.c
index 77b890e4d296..77b890e4d296 100644
--- a/drivers/video/udlfb.c
+++ b/drivers/video/fbdev/udlfb.c
diff --git a/drivers/video/uvesafb.c b/drivers/video/fbdev/uvesafb.c
index 509d452e8f91..509d452e8f91 100644
--- a/drivers/video/uvesafb.c
+++ b/drivers/video/fbdev/uvesafb.c
diff --git a/drivers/video/valkyriefb.c b/drivers/video/fbdev/valkyriefb.c
index 97cb9bd1d1dd..97cb9bd1d1dd 100644
--- a/drivers/video/valkyriefb.c
+++ b/drivers/video/fbdev/valkyriefb.c
diff --git a/drivers/video/valkyriefb.h b/drivers/video/fbdev/valkyriefb.h
index d787441e5a42..d787441e5a42 100644
--- a/drivers/video/valkyriefb.h
+++ b/drivers/video/fbdev/valkyriefb.h
diff --git a/drivers/video/vermilion/Makefile b/drivers/video/fbdev/vermilion/Makefile
index cc21a656153d..cc21a656153d 100644
--- a/drivers/video/vermilion/Makefile
+++ b/drivers/video/fbdev/vermilion/Makefile
diff --git a/drivers/video/vermilion/cr_pll.c b/drivers/video/fbdev/vermilion/cr_pll.c
index ebc6e6e0dd0f..ebc6e6e0dd0f 100644
--- a/drivers/video/vermilion/cr_pll.c
+++ b/drivers/video/fbdev/vermilion/cr_pll.c
diff --git a/drivers/video/vermilion/vermilion.c b/drivers/video/fbdev/vermilion/vermilion.c
index 048a66640b03..048a66640b03 100644
--- a/drivers/video/vermilion/vermilion.c
+++ b/drivers/video/fbdev/vermilion/vermilion.c
diff --git a/drivers/video/vermilion/vermilion.h b/drivers/video/fbdev/vermilion/vermilion.h
index 43d11ec197fc..43d11ec197fc 100644
--- a/drivers/video/vermilion/vermilion.h
+++ b/drivers/video/fbdev/vermilion/vermilion.h
diff --git a/drivers/video/vesafb.c b/drivers/video/fbdev/vesafb.c
index 6170e7f58640..6170e7f58640 100644
--- a/drivers/video/vesafb.c
+++ b/drivers/video/fbdev/vesafb.c
diff --git a/drivers/video/vfb.c b/drivers/video/fbdev/vfb.c
index 70a897b1e458..70a897b1e458 100644
--- a/drivers/video/vfb.c
+++ b/drivers/video/fbdev/vfb.c
diff --git a/drivers/video/vga16fb.c b/drivers/video/fbdev/vga16fb.c
index 283d335a759f..283d335a759f 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/fbdev/vga16fb.c
diff --git a/drivers/video/via/Makefile b/drivers/video/fbdev/via/Makefile
index 159f26e6adb5..159f26e6adb5 100644
--- a/drivers/video/via/Makefile
+++ b/drivers/video/fbdev/via/Makefile
diff --git a/drivers/video/via/accel.c b/drivers/video/fbdev/via/accel.c
index 4b67b8e6030a..4b67b8e6030a 100644
--- a/drivers/video/via/accel.c
+++ b/drivers/video/fbdev/via/accel.c
diff --git a/drivers/video/via/accel.h b/drivers/video/fbdev/via/accel.h
index 79d5e10cc835..79d5e10cc835 100644
--- a/drivers/video/via/accel.h
+++ b/drivers/video/fbdev/via/accel.h
diff --git a/drivers/video/via/chip.h b/drivers/video/fbdev/via/chip.h
index d32a5076c20f..d32a5076c20f 100644
--- a/drivers/video/via/chip.h
+++ b/drivers/video/fbdev/via/chip.h
diff --git a/drivers/video/via/debug.h b/drivers/video/fbdev/via/debug.h
index 86eacc2017f3..86eacc2017f3 100644
--- a/drivers/video/via/debug.h
+++ b/drivers/video/fbdev/via/debug.h
diff --git a/drivers/video/via/dvi.c b/drivers/video/fbdev/via/dvi.c
index 7789553952d3..7789553952d3 100644
--- a/drivers/video/via/dvi.c
+++ b/drivers/video/fbdev/via/dvi.c
diff --git a/drivers/video/via/dvi.h b/drivers/video/fbdev/via/dvi.h
index 4c6bfba57d11..4c6bfba57d11 100644
--- a/drivers/video/via/dvi.h
+++ b/drivers/video/fbdev/via/dvi.h
diff --git a/drivers/video/via/global.c b/drivers/video/fbdev/via/global.c
index 3102171c1674..3102171c1674 100644
--- a/drivers/video/via/global.c
+++ b/drivers/video/fbdev/via/global.c
diff --git a/drivers/video/via/global.h b/drivers/video/fbdev/via/global.h
index 275dbbbd6b81..275dbbbd6b81 100644
--- a/drivers/video/via/global.h
+++ b/drivers/video/fbdev/via/global.h
diff --git a/drivers/video/via/hw.c b/drivers/video/fbdev/via/hw.c
index 22450908306c..22450908306c 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/fbdev/via/hw.c
diff --git a/drivers/video/via/hw.h b/drivers/video/fbdev/via/hw.h
index 3be073c58b03..3be073c58b03 100644
--- a/drivers/video/via/hw.h
+++ b/drivers/video/fbdev/via/hw.h
diff --git a/drivers/video/via/ioctl.c b/drivers/video/fbdev/via/ioctl.c
index ea1c51428823..ea1c51428823 100644
--- a/drivers/video/via/ioctl.c
+++ b/drivers/video/fbdev/via/ioctl.c
diff --git a/drivers/video/via/ioctl.h b/drivers/video/fbdev/via/ioctl.h
index 6010d10b59e8..6010d10b59e8 100644
--- a/drivers/video/via/ioctl.h
+++ b/drivers/video/fbdev/via/ioctl.h
diff --git a/drivers/video/via/lcd.c b/drivers/video/fbdev/via/lcd.c
index 5d21ff436ec8..5d21ff436ec8 100644
--- a/drivers/video/via/lcd.c
+++ b/drivers/video/fbdev/via/lcd.c
diff --git a/drivers/video/via/lcd.h b/drivers/video/fbdev/via/lcd.h
index 5c988a063ad5..5c988a063ad5 100644
--- a/drivers/video/via/lcd.h
+++ b/drivers/video/fbdev/via/lcd.h
diff --git a/drivers/video/via/share.h b/drivers/video/fbdev/via/share.h
index 65c65c611e0a..65c65c611e0a 100644
--- a/drivers/video/via/share.h
+++ b/drivers/video/fbdev/via/share.h
diff --git a/drivers/video/via/tblDPASetting.c b/drivers/video/fbdev/via/tblDPASetting.c
index 73bb554e7c1e..73bb554e7c1e 100644
--- a/drivers/video/via/tblDPASetting.c
+++ b/drivers/video/fbdev/via/tblDPASetting.c
diff --git a/drivers/video/via/tblDPASetting.h b/drivers/video/fbdev/via/tblDPASetting.h
index 6db61519cb5d..6db61519cb5d 100644
--- a/drivers/video/via/tblDPASetting.h
+++ b/drivers/video/fbdev/via/tblDPASetting.h
diff --git a/drivers/video/via/via-core.c b/drivers/video/fbdev/via/via-core.c
index 6e274825fb31..6e274825fb31 100644
--- a/drivers/video/via/via-core.c
+++ b/drivers/video/fbdev/via/via-core.c
diff --git a/drivers/video/via/via-gpio.c b/drivers/video/fbdev/via/via-gpio.c
index e408679081ab..e408679081ab 100644
--- a/drivers/video/via/via-gpio.c
+++ b/drivers/video/fbdev/via/via-gpio.c
diff --git a/drivers/video/via/via_aux.c b/drivers/video/fbdev/via/via_aux.c
index 4a0a55cdac3d..4a0a55cdac3d 100644
--- a/drivers/video/via/via_aux.c
+++ b/drivers/video/fbdev/via/via_aux.c
diff --git a/drivers/video/via/via_aux.h b/drivers/video/fbdev/via/via_aux.h
index a8de3f038cea..a8de3f038cea 100644
--- a/drivers/video/via/via_aux.h
+++ b/drivers/video/fbdev/via/via_aux.h
diff --git a/drivers/video/via/via_aux_ch7301.c b/drivers/video/fbdev/via/via_aux_ch7301.c
index 1cbe5037a6b0..1cbe5037a6b0 100644
--- a/drivers/video/via/via_aux_ch7301.c
+++ b/drivers/video/fbdev/via/via_aux_ch7301.c
diff --git a/drivers/video/via/via_aux_edid.c b/drivers/video/fbdev/via/via_aux_edid.c
index 754d4509033f..754d4509033f 100644
--- a/drivers/video/via/via_aux_edid.c
+++ b/drivers/video/fbdev/via/via_aux_edid.c
diff --git a/drivers/video/via/via_aux_sii164.c b/drivers/video/fbdev/via/via_aux_sii164.c
index ca1b35f033b1..ca1b35f033b1 100644
--- a/drivers/video/via/via_aux_sii164.c
+++ b/drivers/video/fbdev/via/via_aux_sii164.c
diff --git a/drivers/video/via/via_aux_vt1621.c b/drivers/video/fbdev/via/via_aux_vt1621.c
index 38eca8479898..38eca8479898 100644
--- a/drivers/video/via/via_aux_vt1621.c
+++ b/drivers/video/fbdev/via/via_aux_vt1621.c
diff --git a/drivers/video/via/via_aux_vt1622.c b/drivers/video/fbdev/via/via_aux_vt1622.c
index 8c79c68ba683..8c79c68ba683 100644
--- a/drivers/video/via/via_aux_vt1622.c
+++ b/drivers/video/fbdev/via/via_aux_vt1622.c
diff --git a/drivers/video/via/via_aux_vt1625.c b/drivers/video/fbdev/via/via_aux_vt1625.c
index 03eb30165d36..03eb30165d36 100644
--- a/drivers/video/via/via_aux_vt1625.c
+++ b/drivers/video/fbdev/via/via_aux_vt1625.c
diff --git a/drivers/video/via/via_aux_vt1631.c b/drivers/video/fbdev/via/via_aux_vt1631.c
index 06e742f1f723..06e742f1f723 100644
--- a/drivers/video/via/via_aux_vt1631.c
+++ b/drivers/video/fbdev/via/via_aux_vt1631.c
diff --git a/drivers/video/via/via_aux_vt1632.c b/drivers/video/fbdev/via/via_aux_vt1632.c
index d24f4cd97401..d24f4cd97401 100644
--- a/drivers/video/via/via_aux_vt1632.c
+++ b/drivers/video/fbdev/via/via_aux_vt1632.c
diff --git a/drivers/video/via/via_aux_vt1636.c b/drivers/video/fbdev/via/via_aux_vt1636.c
index 9e015c101d4d..9e015c101d4d 100644
--- a/drivers/video/via/via_aux_vt1636.c
+++ b/drivers/video/fbdev/via/via_aux_vt1636.c
diff --git a/drivers/video/via/via_clock.c b/drivers/video/fbdev/via/via_clock.c
index db1e39277e32..db1e39277e32 100644
--- a/drivers/video/via/via_clock.c
+++ b/drivers/video/fbdev/via/via_clock.c
diff --git a/drivers/video/via/via_clock.h b/drivers/video/fbdev/via/via_clock.h
index 88714ae0d157..88714ae0d157 100644
--- a/drivers/video/via/via_clock.h
+++ b/drivers/video/fbdev/via/via_clock.h
diff --git a/drivers/video/via/via_i2c.c b/drivers/video/fbdev/via/via_i2c.c
index dd53058bbbb7..dd53058bbbb7 100644
--- a/drivers/video/via/via_i2c.c
+++ b/drivers/video/fbdev/via/via_i2c.c
diff --git a/drivers/video/via/via_modesetting.c b/drivers/video/fbdev/via/via_modesetting.c
index 0b414b09b9b4..0b414b09b9b4 100644
--- a/drivers/video/via/via_modesetting.c
+++ b/drivers/video/fbdev/via/via_modesetting.c
diff --git a/drivers/video/via/via_modesetting.h b/drivers/video/fbdev/via/via_modesetting.h
index f6a6503da3b3..f6a6503da3b3 100644
--- a/drivers/video/via/via_modesetting.h
+++ b/drivers/video/fbdev/via/via_modesetting.h
diff --git a/drivers/video/via/via_utility.c b/drivers/video/fbdev/via/via_utility.c
index 35458a5eadc8..35458a5eadc8 100644
--- a/drivers/video/via/via_utility.c
+++ b/drivers/video/fbdev/via/via_utility.c
diff --git a/drivers/video/via/via_utility.h b/drivers/video/fbdev/via/via_utility.h
index f23be1708c14..f23be1708c14 100644
--- a/drivers/video/via/via_utility.h
+++ b/drivers/video/fbdev/via/via_utility.h
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/fbdev/via/viafbdev.c
index 325c43c6ff97..325c43c6ff97 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/fbdev/via/viafbdev.c
diff --git a/drivers/video/via/viafbdev.h b/drivers/video/fbdev/via/viafbdev.h
index f6b2ddf56e94..f6b2ddf56e94 100644
--- a/drivers/video/via/viafbdev.h
+++ b/drivers/video/fbdev/via/viafbdev.h
diff --git a/drivers/video/via/viamode.c b/drivers/video/fbdev/via/viamode.c
index 0666ab01cf4a..0666ab01cf4a 100644
--- a/drivers/video/via/viamode.c
+++ b/drivers/video/fbdev/via/viamode.c
diff --git a/drivers/video/via/viamode.h b/drivers/video/fbdev/via/viamode.h
index dd19106698e7..dd19106698e7 100644
--- a/drivers/video/via/viamode.h
+++ b/drivers/video/fbdev/via/viamode.h
diff --git a/drivers/video/via/vt1636.c b/drivers/video/fbdev/via/vt1636.c
index ee2903b472cf..ee2903b472cf 100644
--- a/drivers/video/via/vt1636.c
+++ b/drivers/video/fbdev/via/vt1636.c
diff --git a/drivers/video/via/vt1636.h b/drivers/video/fbdev/via/vt1636.h
index 4c1314e57468..4c1314e57468 100644
--- a/drivers/video/via/vt1636.h
+++ b/drivers/video/fbdev/via/vt1636.h
diff --git a/drivers/video/vt8500lcdfb.c b/drivers/video/fbdev/vt8500lcdfb.c
index a8f2b280f796..a8f2b280f796 100644
--- a/drivers/video/vt8500lcdfb.c
+++ b/drivers/video/fbdev/vt8500lcdfb.c
diff --git a/drivers/video/vt8500lcdfb.h b/drivers/video/fbdev/vt8500lcdfb.h
index 36ca3ca09d83..36ca3ca09d83 100644
--- a/drivers/video/vt8500lcdfb.h
+++ b/drivers/video/fbdev/vt8500lcdfb.h
diff --git a/drivers/video/vt8623fb.c b/drivers/video/fbdev/vt8623fb.c
index 5c7cbc6c6236..5c7cbc6c6236 100644
--- a/drivers/video/vt8623fb.c
+++ b/drivers/video/fbdev/vt8623fb.c
diff --git a/drivers/video/w100fb.c b/drivers/video/fbdev/w100fb.c
index 10951c82f6ed..10951c82f6ed 100644
--- a/drivers/video/w100fb.c
+++ b/drivers/video/fbdev/w100fb.c
diff --git a/drivers/video/w100fb.h b/drivers/video/fbdev/w100fb.h
index fffae7b4f6e9..fffae7b4f6e9 100644
--- a/drivers/video/w100fb.h
+++ b/drivers/video/fbdev/w100fb.h
diff --git a/drivers/video/wm8505fb.c b/drivers/video/fbdev/wm8505fb.c
index 537d199612af..537d199612af 100644
--- a/drivers/video/wm8505fb.c
+++ b/drivers/video/fbdev/wm8505fb.c
diff --git a/drivers/video/wm8505fb_regs.h b/drivers/video/fbdev/wm8505fb_regs.h
index 4dd41668c6d1..4dd41668c6d1 100644
--- a/drivers/video/wm8505fb_regs.h
+++ b/drivers/video/fbdev/wm8505fb_regs.h
diff --git a/drivers/video/wmt_ge_rops.c b/drivers/video/fbdev/wmt_ge_rops.c
index b0a9f34b2e01..9df6fe78a44b 100644
--- a/drivers/video/wmt_ge_rops.c
+++ b/drivers/video/fbdev/wmt_ge_rops.c
@@ -18,7 +18,7 @@
#include <linux/module.h>
#include <linux/fb.h>
#include <linux/platform_device.h>
-#include "fb_draw.h"
+#include "core/fb_draw.h"
#define GE_COMMAND_OFF 0x00
#define GE_DEPTH_OFF 0x04
diff --git a/drivers/video/wmt_ge_rops.h b/drivers/video/fbdev/wmt_ge_rops.h
index f73ec6377a46..f73ec6377a46 100644
--- a/drivers/video/wmt_ge_rops.h
+++ b/drivers/video/fbdev/wmt_ge_rops.h
diff --git a/drivers/video/xen-fbfront.c b/drivers/video/fbdev/xen-fbfront.c
index 901014bbc821..901014bbc821 100644
--- a/drivers/video/xen-fbfront.c
+++ b/drivers/video/fbdev/xen-fbfront.c
diff --git a/drivers/video/xilinxfb.c b/drivers/video/fbdev/xilinxfb.c
index 553cff2f3f4c..553cff2f3f4c 100644
--- a/drivers/video/xilinxfb.c
+++ b/drivers/video/fbdev/xilinxfb.c
diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig
deleted file mode 100644
index 63b23f87081d..000000000000
--- a/drivers/video/omap2/Kconfig
+++ /dev/null
@@ -1,10 +0,0 @@
-config OMAP2_VRFB
- bool
-
-if ARCH_OMAP2PLUS
-
-source "drivers/video/omap2/dss/Kconfig"
-source "drivers/video/omap2/omapfb/Kconfig"
-source "drivers/video/omap2/displays-new/Kconfig"
-
-endif
diff --git a/drivers/vme/bridges/vme_tsi148.c b/drivers/vme/bridges/vme_tsi148.c
index 06990c6a1a69..61e706c0e00c 100644
--- a/drivers/vme/bridges/vme_tsi148.c
+++ b/drivers/vme/bridges/vme_tsi148.c
@@ -320,7 +320,7 @@ static int tsi148_irq_init(struct vme_bridge *tsi148_bridge)
struct pci_dev *pdev;
struct tsi148_driver *bridge;
- pdev = container_of(tsi148_bridge->parent, struct pci_dev, dev);
+ pdev = to_pci_dev(tsi148_bridge->parent);
bridge = tsi148_bridge->driver_priv;
@@ -433,9 +433,7 @@ static void tsi148_irq_set(struct vme_bridge *tsi148_bridge, int level,
iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO);
if (sync != 0) {
- pdev = container_of(tsi148_bridge->parent,
- struct pci_dev, dev);
-
+ pdev = to_pci_dev(tsi148_bridge->parent);
synchronize_irq(pdev->irq);
}
} else {
@@ -741,7 +739,7 @@ static int tsi148_slave_get(struct vme_slave_resource *image, int *enabled,
reg_join(vme_bound_high, vme_bound_low, &vme_bound);
reg_join(pci_offset_high, pci_offset_low, &pci_offset);
- *pci_base = (dma_addr_t)vme_base + pci_offset;
+ *pci_base = (dma_addr_t)(*vme_base + pci_offset);
*enabled = 0;
*aspace = 0;
@@ -814,7 +812,7 @@ static int tsi148_alloc_resource(struct vme_master_resource *image,
tsi148_bridge = image->parent;
- pdev = container_of(tsi148_bridge->parent, struct pci_dev, dev);
+ pdev = to_pci_dev(tsi148_bridge->parent);
existing_size = (unsigned long long)(image->bus_resource.end -
image->bus_resource.start);
@@ -910,11 +908,15 @@ static int tsi148_master_set(struct vme_master_resource *image, int enabled,
unsigned long long pci_bound, vme_offset, pci_base;
struct vme_bridge *tsi148_bridge;
struct tsi148_driver *bridge;
+ struct pci_bus_region region;
+ struct pci_dev *pdev;
tsi148_bridge = image->parent;
bridge = tsi148_bridge->driver_priv;
+ pdev = to_pci_dev(tsi148_bridge->parent);
+
/* Verify input data */
if (vme_base & 0xFFFF) {
dev_err(tsi148_bridge->parent, "Invalid VME Window "
@@ -949,7 +951,9 @@ static int tsi148_master_set(struct vme_master_resource *image, int enabled,
pci_bound = 0;
vme_offset = 0;
} else {
- pci_base = (unsigned long long)image->bus_resource.start;
+ pcibios_resource_to_bus(pdev->bus, &region,
+ &image->bus_resource);
+ pci_base = region.start;
/*
* Bound address is a valid address for the window, adjust
@@ -2232,7 +2236,7 @@ static void *tsi148_alloc_consistent(struct device *parent, size_t size,
struct pci_dev *pdev;
/* Find pci_dev container of dev */
- pdev = container_of(parent, struct pci_dev, dev);
+ pdev = to_pci_dev(parent);
return pci_alloc_consistent(pdev, size, dma);
}
@@ -2243,7 +2247,7 @@ static void tsi148_free_consistent(struct device *parent, size_t size,
struct pci_dev *pdev;
/* Find pci_dev container of dev */
- pdev = container_of(parent, struct pci_dev, dev);
+ pdev = to_pci_dev(parent);
pci_free_consistent(pdev, size, vaddr, dma);
}
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index b96f61b15dc6..ff52618cafbe 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -614,27 +614,11 @@ end:
return err;
}
-/*
- * Handle sysfs file creation and removal here, before userspace is told that
- * the device is added / removed from the system
- */
-static int w1_bus_notify(struct notifier_block *nb, unsigned long action,
- void *data)
+static int w1_family_notify(unsigned long action, struct w1_slave *sl)
{
- struct device *dev = data;
- struct w1_slave *sl;
struct w1_family_ops *fops;
int err;
- /*
- * Only care about slave devices at the moment. Yes, we should use a
- * separate "type" for this, but for now, look at the release function
- * to know which type it is...
- */
- if (dev->release != w1_slave_release)
- return 0;
-
- sl = dev_to_w1_slave(dev);
fops = sl->family->fops;
if (!fops)
@@ -673,10 +657,6 @@ static int w1_bus_notify(struct notifier_block *nb, unsigned long action,
return 0;
}
-static struct notifier_block w1_bus_nb = {
- .notifier_call = w1_bus_notify,
-};
-
static int __w1_attach_slave_device(struct w1_slave *sl)
{
int err;
@@ -698,6 +678,9 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
dev_dbg(&sl->dev, "%s: registering %s as %p.\n", __func__,
dev_name(&sl->dev), sl);
+ /* suppress for w1_family_notify before sending KOBJ_ADD */
+ dev_set_uevent_suppress(&sl->dev, true);
+
err = device_register(&sl->dev);
if (err < 0) {
dev_err(&sl->dev,
@@ -705,7 +688,7 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
dev_name(&sl->dev), err);
return err;
}
-
+ w1_family_notify(BUS_NOTIFY_ADD_DEVICE, sl);
dev_set_uevent_suppress(&sl->dev, false);
kobject_uevent(&sl->dev.kobj, KOBJ_ADD);
@@ -799,6 +782,7 @@ int w1_unref_slave(struct w1_slave *sl)
msg.type = W1_SLAVE_REMOVE;
w1_netlink_send(sl->master, &msg);
+ w1_family_notify(BUS_NOTIFY_DEL_DEVICE, sl);
device_unregister(&sl->dev);
#ifdef DEBUG
memset(sl, 0, sizeof(*sl));
@@ -1186,10 +1170,6 @@ static int __init w1_init(void)
goto err_out_exit_init;
}
- retval = bus_register_notifier(&w1_bus_type, &w1_bus_nb);
- if (retval)
- goto err_out_bus_unregister;
-
retval = driver_register(&w1_master_driver);
if (retval) {
printk(KERN_ERR
diff --git a/drivers/w1/w1_netlink.c b/drivers/w1/w1_netlink.c
index 5234964fe001..a02704a59321 100644
--- a/drivers/w1/w1_netlink.c
+++ b/drivers/w1/w1_netlink.c
@@ -300,12 +300,6 @@ static int w1_process_command_root(struct cn_msg *msg,
struct w1_netlink_msg *w;
u32 *id;
- if (mcmd->type != W1_LIST_MASTERS) {
- printk(KERN_NOTICE "%s: msg: %x.%x, wrong type: %u, len: %u.\n",
- __func__, msg->id.idx, msg->id.val, mcmd->type, mcmd->len);
- return -EPROTO;
- }
-
cn = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!cn)
return -ENOMEM;
@@ -441,6 +435,9 @@ static void w1_process_cb(struct w1_master *dev, struct w1_async_cmd *async_cmd)
w1_netlink_send_error(&node->block->msg, node->m, cmd,
node->block->portid, err);
+ /* ref taken in w1_search_slave or w1_search_master_id when building
+ * the block
+ */
if (sl)
w1_unref_slave(sl);
else
@@ -503,30 +500,42 @@ static void w1_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
msg_len = msg->len;
while (msg_len && !err) {
- struct w1_reg_num id;
- u16 mlen = m->len;
dev = NULL;
sl = NULL;
- memcpy(&id, m->id.id, sizeof(id));
-#if 0
- printk("%s: %02x.%012llx.%02x: type=%02x, len=%u.\n",
- __func__, id.family, (unsigned long long)id.id, id.crc, m->type, m->len);
-#endif
if (m->len + sizeof(struct w1_netlink_msg) > msg_len) {
err = -E2BIG;
break;
}
+ /* execute on this thread, no need to process later */
+ if (m->type == W1_LIST_MASTERS) {
+ err = w1_process_command_root(msg, m, nsp->portid);
+ goto out_cont;
+ }
+
+ /* All following message types require additional data,
+ * check here before references are taken.
+ */
+ if (!m->len) {
+ err = -EPROTO;
+ goto out_cont;
+ }
+
+ /* both search calls take reference counts */
if (m->type == W1_MASTER_CMD) {
dev = w1_search_master_id(m->id.mst.id);
} else if (m->type == W1_SLAVE_CMD) {
- sl = w1_search_slave(&id);
+ sl = w1_search_slave((struct w1_reg_num *)m->id.id);
if (sl)
dev = sl->master;
} else {
- err = w1_process_command_root(msg, m, nsp->portid);
+ printk(KERN_NOTICE
+ "%s: msg: %x.%x, wrong type: %u, len: %u.\n",
+ __func__, msg->id.idx, msg->id.val,
+ m->type, m->len);
+ err = -EPROTO;
goto out_cont;
}
@@ -536,8 +545,6 @@ static void w1_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
}
err = 0;
- if (!mlen)
- goto out_cont;
atomic_inc(&block->refcnt);
node->async.cb = w1_process_cb;
@@ -557,7 +564,8 @@ out_cont:
if (err)
w1_netlink_send_error(msg, m, NULL, nsp->portid, err);
msg_len -= sizeof(struct w1_netlink_msg) + m->len;
- m = (struct w1_netlink_msg *)(((u8 *)m) + sizeof(struct w1_netlink_msg) + m->len);
+ m = (struct w1_netlink_msg *)(((u8 *)m) +
+ sizeof(struct w1_netlink_msg) + m->len);
/*
* Let's allow requests for nonexisting devices.
diff --git a/drivers/xen/events/events_fifo.c b/drivers/xen/events/events_fifo.c
index 96109a9972b6..84b4bfb84344 100644
--- a/drivers/xen/events/events_fifo.c
+++ b/drivers/xen/events/events_fifo.c
@@ -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);
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c
index fc6c94c0b436..c3667b202f2f 100644
--- a/drivers/xen/manage.c
+++ b/drivers/xen/manage.c
@@ -41,9 +41,6 @@ static enum shutdown_state shutting_down = SHUTDOWN_INVALID;
struct suspend_info {
int cancelled;
- unsigned long arg; /* extra hypercall argument */
- void (*pre)(void);
- void (*post)(int cancelled);
};
static RAW_NOTIFIER_HEAD(xen_resume_notifier);
@@ -61,26 +58,6 @@ void xen_resume_notifier_unregister(struct notifier_block *nb)
EXPORT_SYMBOL_GPL(xen_resume_notifier_unregister);
#ifdef CONFIG_HIBERNATE_CALLBACKS
-static void xen_hvm_post_suspend(int cancelled)
-{
- xen_arch_hvm_post_suspend(cancelled);
- gnttab_resume();
-}
-
-static void xen_pre_suspend(void)
-{
- xen_mm_pin_all();
- gnttab_suspend();
- xen_arch_pre_suspend();
-}
-
-static void xen_post_suspend(int cancelled)
-{
- xen_arch_post_suspend(cancelled);
- gnttab_resume();
- xen_mm_unpin_all();
-}
-
static int xen_suspend(void *data)
{
struct suspend_info *si = data;
@@ -94,18 +71,20 @@ static int xen_suspend(void *data)
return err;
}
- if (si->pre)
- si->pre();
+ gnttab_suspend();
+ xen_arch_pre_suspend();
/*
* This hypercall returns 1 if suspend was cancelled
* or the domain was merely checkpointed, and 0 if it
* is resuming in a new domain.
*/
- si->cancelled = HYPERVISOR_suspend(si->arg);
+ si->cancelled = HYPERVISOR_suspend(xen_pv_domain()
+ ? virt_to_mfn(xen_start_info)
+ : 0);
- if (si->post)
- si->post(si->cancelled);
+ xen_arch_post_suspend(si->cancelled);
+ gnttab_resume();
if (!si->cancelled) {
xen_irq_resume();
@@ -154,16 +133,6 @@ static void do_suspend(void)
si.cancelled = 1;
- if (xen_hvm_domain()) {
- si.arg = 0UL;
- si.pre = NULL;
- si.post = &xen_hvm_post_suspend;
- } else {
- si.arg = virt_to_mfn(xen_start_info);
- si.pre = &xen_pre_suspend;
- si.post = &xen_post_suspend;
- }
-
err = stop_machine(xen_suspend, &si, cpumask_of(0));
raw_notifier_call_chain(&xen_resume_notifier, 0, NULL);
@@ -198,10 +167,32 @@ struct shutdown_handler {
void (*cb)(void);
};
+static int poweroff_nb(struct notifier_block *cb, unsigned long code, void *unused)
+{
+ switch (code) {
+ case SYS_DOWN:
+ case SYS_HALT:
+ case SYS_POWER_OFF:
+ shutting_down = SHUTDOWN_POWEROFF;
+ default:
+ break;
+ }
+ return NOTIFY_DONE;
+}
static void do_poweroff(void)
{
- shutting_down = SHUTDOWN_POWEROFF;
- orderly_poweroff(false);
+ switch (system_state) {
+ case SYSTEM_BOOTING:
+ orderly_poweroff(true);
+ break;
+ case SYSTEM_RUNNING:
+ orderly_poweroff(false);
+ break;
+ default:
+ /* Don't do it when we are halting/rebooting. */
+ pr_info("Ignoring Xen toolstack shutdown.\n");
+ break;
+ }
}
static void do_reboot(void)
@@ -307,6 +298,10 @@ static struct xenbus_watch shutdown_watch = {
.callback = shutdown_handler
};
+static struct notifier_block xen_reboot_nb = {
+ .notifier_call = poweroff_nb,
+};
+
static int setup_shutdown_watcher(void)
{
int err;
@@ -317,6 +312,7 @@ static int setup_shutdown_watcher(void)
return err;
}
+
#ifdef CONFIG_MAGIC_SYSRQ
err = register_xenbus_watch(&sysrq_watch);
if (err) {
@@ -345,6 +341,7 @@ int xen_setup_shutdown_event(void)
if (!xen_domain())
return -ENODEV;
register_xenstore_notifier(&xenstore_notifier);
+ register_reboot_notifier(&xen_reboot_nb);
return 0;
}
diff --git a/drivers/xen/xen-acpi-processor.c b/drivers/xen/xen-acpi-processor.c
index 82358d14ecf1..59fc190f1e92 100644
--- a/drivers/xen/xen-acpi-processor.c
+++ b/drivers/xen/xen-acpi-processor.c
@@ -127,7 +127,7 @@ static int push_cxx_to_hypervisor(struct acpi_processor *_pr)
pr_debug(" C%d: %s %d uS\n",
cx->type, cx->desc, (u32)cx->latency);
}
- } else if (ret != -EINVAL)
+ } else if ((ret != -EINVAL) && (ret != -ENOSYS))
/* EINVAL means the ACPI ID is incorrect - meaning the ACPI
* table is referencing a non-existing CPU - which can happen
* with broken ACPI tables. */
@@ -259,7 +259,7 @@ static int push_pxx_to_hypervisor(struct acpi_processor *_pr)
(u32) perf->states[i].power,
(u32) perf->states[i].transition_latency);
}
- } else if (ret != -EINVAL)
+ } else if ((ret != -EINVAL) && (ret != -ENOSYS))
/* EINVAL means the ACPI ID is incorrect - meaning the ACPI
* table is referencing a non-existing CPU - which can happen
* with broken ACPI tables. */
diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c
index 62fcd485f0a7..d57a173685f3 100644
--- a/drivers/xen/xen-pciback/pci_stub.c
+++ b/drivers/xen/xen-pciback/pci_stub.c
@@ -242,6 +242,15 @@ struct pci_dev *pcistub_get_pci_dev(struct xen_pcibk_device *pdev,
return found_dev;
}
+/*
+ * Called when:
+ * - XenBus state has been reconfigure (pci unplug). See xen_pcibk_remove_device
+ * - XenBus state has been disconnected (guest shutdown). See xen_pcibk_xenbus_remove
+ * - 'echo BDF > unbind' on pciback module with no guest attached. See pcistub_remove
+ * - 'echo BDF > unbind' with a guest still using it. See pcistub_remove
+ *
+ * As such we have to be careful.
+ */
void pcistub_put_pci_dev(struct pci_dev *dev)
{
struct pcistub_device *psdev, *found_psdev = NULL;
@@ -272,16 +281,16 @@ void pcistub_put_pci_dev(struct pci_dev *dev)
* and want to inhibit the user from fiddling with 'reset'
*/
pci_reset_function(dev);
- pci_restore_state(psdev->dev);
+ pci_restore_state(dev);
/* This disables the device. */
- xen_pcibk_reset_device(found_psdev->dev);
+ xen_pcibk_reset_device(dev);
/* And cleanup up our emulated fields. */
- xen_pcibk_config_free_dyn_fields(found_psdev->dev);
- xen_pcibk_config_reset_dev(found_psdev->dev);
+ xen_pcibk_config_reset_dev(dev);
+ xen_pcibk_config_free_dyn_fields(dev);
- xen_unregister_device_domain_owner(found_psdev->dev);
+ xen_unregister_device_domain_owner(dev);
spin_lock_irqsave(&found_psdev->lock, flags);
found_psdev->pdev = NULL;
@@ -493,6 +502,8 @@ static int pcistub_seize(struct pci_dev *dev)
return err;
}
+/* Called when 'bind'. This means we must _NOT_ call pci_reset_function or
+ * other functions that take the sysfs lock. */
static int pcistub_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
int err = 0;
@@ -520,6 +531,8 @@ out:
return err;
}
+/* Called when 'unbind'. This means we must _NOT_ call pci_reset_function or
+ * other functions that take the sysfs lock. */
static void pcistub_remove(struct pci_dev *dev)
{
struct pcistub_device *psdev, *found_psdev = NULL;
@@ -551,6 +564,8 @@ static void pcistub_remove(struct pci_dev *dev)
pr_warn("****** shutdown driver domain before binding device\n");
pr_warn("****** to other drivers or domains\n");
+ /* N.B. This ends up calling pcistub_put_pci_dev which ends up
+ * doing the FLR. */
xen_pcibk_release_pci_dev(found_psdev->pdev,
found_psdev->dev);
}
diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c
index 929dd46bb40c..607e41460c0d 100644
--- a/drivers/xen/xen-pciback/pciback_ops.c
+++ b/drivers/xen/xen-pciback/pciback_ops.c
@@ -217,7 +217,7 @@ int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev,
if (result == 0) {
for (i = 0; i < op->value; i++) {
op->msix_entries[i].entry = entries[i].entry;
- if (entries[i].vector)
+ if (entries[i].vector) {
op->msix_entries[i].vector =
xen_pirq_from_irq(entries[i].vector);
if (unlikely(verbose_request))
@@ -225,6 +225,7 @@ int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev,
"MSI-X[%d]: %d\n",
pci_name(dev), i,
op->msix_entries[i].vector);
+ }
}
} else
pr_warn_ratelimited("%s: error enabling MSI-X for guest %u: err %d!\n",
diff --git a/drivers/xen/xen-pciback/vpci.c b/drivers/xen/xen-pciback/vpci.c
index 3165ce361b00..51afff96c515 100644
--- a/drivers/xen/xen-pciback/vpci.c
+++ b/drivers/xen/xen-pciback/vpci.c
@@ -137,6 +137,8 @@ unlock:
/* Publish this device. */
if (!err)
err = publish_cb(pdev, 0, 0, PCI_DEVFN(slot, func), devid);
+ else
+ kfree(dev_entry);
out:
return err;
diff --git a/drivers/xen/xen-pciback/xenbus.c b/drivers/xen/xen-pciback/xenbus.c
index a9ed867afaba..4a7e6e0a5f4c 100644
--- a/drivers/xen/xen-pciback/xenbus.c
+++ b/drivers/xen/xen-pciback/xenbus.c
@@ -93,6 +93,8 @@ static void free_pdev(struct xen_pcibk_device *pdev)
xen_pcibk_disconnect(pdev);
+ /* N.B. This calls pcistub_put_pci_dev which does the FLR on all
+ * of the PCIe devices. */
xen_pcibk_release_devices(pdev);
dev_set_drvdata(&pdev->xdev->dev, NULL);
@@ -286,6 +288,8 @@ static int xen_pcibk_remove_device(struct xen_pcibk_device *pdev,
dev_dbg(&dev->dev, "unregistering for %d\n", pdev->xdev->otherend_id);
xen_unregister_device_domain_owner(dev);
+ /* N.B. This ends up calling pcistub_put_pci_dev which ends up
+ * doing the FLR. */
xen_pcibk_release_pci_dev(pdev, dev);
out:
diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c
index b6d5fff43d16..ba804f3d8278 100644
--- a/drivers/xen/xenbus/xenbus_xs.c
+++ b/drivers/xen/xenbus/xenbus_xs.c
@@ -50,6 +50,7 @@
#include <xen/xenbus.h>
#include <xen/xen.h>
#include "xenbus_comms.h"
+#include "xenbus_probe.h"
struct xs_stored_msg {
struct list_head list;
@@ -139,6 +140,29 @@ static int get_error(const char *errorstring)
return xsd_errors[i].errnum;
}
+static bool xenbus_ok(void)
+{
+ switch (xen_store_domain_type) {
+ case XS_LOCAL:
+ switch (system_state) {
+ case SYSTEM_POWER_OFF:
+ case SYSTEM_RESTART:
+ case SYSTEM_HALT:
+ return false;
+ default:
+ break;
+ }
+ return true;
+ case XS_PV:
+ case XS_HVM:
+ /* FIXME: Could check that the remote domain is alive,
+ * but it is normally initial domain. */
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len)
{
struct xs_stored_msg *msg;
@@ -148,9 +172,20 @@ static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len)
while (list_empty(&xs_state.reply_list)) {
spin_unlock(&xs_state.reply_lock);
- /* XXX FIXME: Avoid synchronous wait for response here. */
- wait_event(xs_state.reply_waitq,
- !list_empty(&xs_state.reply_list));
+ if (xenbus_ok())
+ /* XXX FIXME: Avoid synchronous wait for response here. */
+ wait_event_timeout(xs_state.reply_waitq,
+ !list_empty(&xs_state.reply_list),
+ msecs_to_jiffies(500));
+ else {
+ /*
+ * If we are in the process of being shut-down there is
+ * no point of trying to contact XenBus - it is either
+ * killed (xenstored application) or the other domain
+ * has been killed or is unreachable.
+ */
+ return ERR_PTR(-EIO);
+ }
spin_lock(&xs_state.reply_lock);
}
@@ -215,6 +250,9 @@ void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg)
mutex_unlock(&xs_state.request_mutex);
+ if (IS_ERR(ret))
+ return ret;
+
if ((msg->type == XS_TRANSACTION_END) ||
((req_msg.type == XS_TRANSACTION_START) &&
(msg->type == XS_ERROR)))
diff --git a/firmware/WHENCE b/firmware/WHENCE
index 8388f02de2bd..0c4d96dee9b6 100644
--- a/firmware/WHENCE
+++ b/firmware/WHENCE
@@ -273,16 +273,6 @@ Converted from Intel HEX files, used in our binary representation of ihex.
--------------------------------------------------------------------------
-Driver: ip2 -- Computone IntelliPort Plus serial device
-
-File: intelliport2.bin
-
-Licence: Unknown
-
-Found in hex form in kernel source.
-
---------------------------------------------------------------------------
-
Driver: CPiA2 -- cameras based on Vision's CPiA2
File: cpia2/stv0672_vp4.bin
diff --git a/fs/affs/super.c b/fs/affs/super.c
index 6d589f28bf9b..895ac7dc9dbf 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -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 */
diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c
index 1c8c6cc6de30..4b0eff6da674 100644
--- a/fs/afs/cmservice.c
+++ b/fs/afs/cmservice.c
@@ -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;
}
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index be75b500005d..590b55f46d61 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -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 */
diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c
index ef943df73b8c..03a3beb17004 100644
--- a/fs/afs/rxrpc.c
+++ b/fs/afs/rxrpc.c
@@ -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
@@ -184,6 +191,28 @@ static void afs_free_call(struct afs_call *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
*/
struct afs_call *afs_alloc_flat_call(const struct afs_call_type *type,
@@ -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]");
}
diff --git a/fs/aio.c b/fs/aio.c
index 12a3de0ee6da..a0ed6c7d2cd2 100644
--- 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);
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 2caf36ac3e93..cc87c1abac97 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -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;
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 4c48df572bd6..ba6b88528dc7 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -2058,6 +2058,20 @@ struct btrfs_ioctl_defrag_range_args {
#define btrfs_raw_test_opt(o, opt) ((o) & BTRFS_MOUNT_##opt)
#define btrfs_test_opt(root, opt) ((root)->fs_info->mount_opt & \
BTRFS_MOUNT_##opt)
+#define btrfs_set_and_info(root, opt, fmt, args...) \
+{ \
+ if (!btrfs_test_opt(root, opt)) \
+ btrfs_info(root->fs_info, fmt, ##args); \
+ btrfs_set_opt(root->fs_info->mount_opt, opt); \
+}
+
+#define btrfs_clear_and_info(root, opt, fmt, args...) \
+{ \
+ if (btrfs_test_opt(root, opt)) \
+ btrfs_info(root->fs_info, fmt, ##args); \
+ btrfs_clear_opt(root->fs_info->mount_opt, opt); \
+}
+
/*
* Inode flags
*/
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 029d46c2e170..983314932af3 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -2861,7 +2861,7 @@ retry_root_backup:
printk(KERN_ERR "BTRFS: failed to read log tree\n");
free_extent_buffer(log_tree_root->node);
kfree(log_tree_root);
- goto fail_trans_kthread;
+ goto fail_qgroup;
}
/* returns with log_tree_root freed on success */
ret = btrfs_recover_log_trees(log_tree_root);
@@ -2870,24 +2870,24 @@ retry_root_backup:
"Failed to recover log tree");
free_extent_buffer(log_tree_root->node);
kfree(log_tree_root);
- goto fail_trans_kthread;
+ goto fail_qgroup;
}
if (sb->s_flags & MS_RDONLY) {
ret = btrfs_commit_super(tree_root);
if (ret)
- goto fail_trans_kthread;
+ goto fail_qgroup;
}
}
ret = btrfs_find_orphan_roots(tree_root);
if (ret)
- goto fail_trans_kthread;
+ goto fail_qgroup;
if (!(sb->s_flags & MS_RDONLY)) {
ret = btrfs_cleanup_fs_roots(fs_info);
if (ret)
- goto fail_trans_kthread;
+ goto fail_qgroup;
ret = btrfs_recover_relocation(tree_root);
if (ret < 0) {
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 1306487c82cf..5590af92094b 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -1542,6 +1542,7 @@ again:
ret = 0;
}
if (ret) {
+ key.objectid = bytenr;
key.type = BTRFS_EXTENT_ITEM_KEY;
key.offset = num_bytes;
btrfs_release_path(path);
@@ -3542,11 +3543,13 @@ static u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags)
return extended_to_chunk(flags | tmp);
}
-static u64 get_alloc_profile(struct btrfs_root *root, u64 flags)
+static u64 get_alloc_profile(struct btrfs_root *root, u64 orig_flags)
{
unsigned seq;
+ u64 flags;
do {
+ flags = orig_flags;
seq = read_seqbegin(&root->fs_info->profiles_lock);
if (flags & BTRFS_BLOCK_GROUP_DATA)
@@ -5719,6 +5722,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
if (ret > 0 && skinny_metadata) {
skinny_metadata = false;
+ key.objectid = bytenr;
key.type = BTRFS_EXTENT_ITEM_KEY;
key.offset = num_bytes;
btrfs_release_path(path);
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index eb742c07e7a4..ae6af072b635 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -800,7 +800,7 @@ next_slot:
if (start > key.offset && end < extent_end) {
BUG_ON(del_nr > 0);
if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
- ret = -EINVAL;
+ ret = -EOPNOTSUPP;
break;
}
@@ -846,7 +846,7 @@ next_slot:
*/
if (start <= key.offset && end < extent_end) {
if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
- ret = -EINVAL;
+ ret = -EOPNOTSUPP;
break;
}
@@ -872,7 +872,7 @@ next_slot:
if (start > key.offset && end >= extent_end) {
BUG_ON(del_nr > 0);
if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
- ret = -EINVAL;
+ ret = -EOPNOTSUPP;
break;
}
@@ -1777,7 +1777,7 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
start_pos = round_down(pos, root->sectorsize);
if (start_pos > i_size_read(inode)) {
/* Expand hole size to cover write data, preventing empty gap */
- end_pos = round_up(pos + iov->iov_len, root->sectorsize);
+ end_pos = round_up(pos + count, root->sectorsize);
err = btrfs_cont_expand(inode, i_size_read(inode), end_pos);
if (err) {
mutex_unlock(&inode->i_mutex);
diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c
index cc8ca193d830..86935f5ae291 100644
--- a/fs/btrfs/inode-map.c
+++ b/fs/btrfs/inode-map.c
@@ -176,7 +176,11 @@ static void start_caching(struct btrfs_root *root)
tsk = kthread_run(caching_kthread, root, "btrfs-ino-cache-%llu\n",
root->root_key.objectid);
- BUG_ON(IS_ERR(tsk)); /* -ENOMEM */
+ if (IS_ERR(tsk)) {
+ btrfs_warn(root->fs_info, "failed to start inode caching task");
+ btrfs_clear_and_info(root, CHANGE_INODE_CACHE,
+ "disabling inode map caching");
+ }
}
int btrfs_find_free_ino(struct btrfs_root *root, u64 *objectid)
@@ -205,24 +209,14 @@ again:
void btrfs_return_ino(struct btrfs_root *root, u64 objectid)
{
- struct btrfs_free_space_ctl *ctl = root->free_ino_ctl;
struct btrfs_free_space_ctl *pinned = root->free_ino_pinned;
if (!btrfs_test_opt(root, INODE_MAP_CACHE))
return;
-
again:
if (root->cached == BTRFS_CACHE_FINISHED) {
- __btrfs_add_free_space(ctl, objectid, 1);
+ __btrfs_add_free_space(pinned, objectid, 1);
} else {
- /*
- * If we are in the process of caching free ino chunks,
- * to avoid adding the same inode number to the free_ino
- * tree twice due to cross transaction, we'll leave it
- * in the pinned tree until a transaction is committed
- * or the caching work is done.
- */
-
down_write(&root->fs_info->commit_root_sem);
spin_lock(&root->cache_lock);
if (root->cached == BTRFS_CACHE_FINISHED) {
@@ -234,11 +228,7 @@ again:
start_caching(root);
- if (objectid <= root->cache_progress ||
- objectid >= root->highest_objectid)
- __btrfs_add_free_space(ctl, objectid, 1);
- else
- __btrfs_add_free_space(pinned, objectid, 1);
+ __btrfs_add_free_space(pinned, objectid, 1);
up_write(&root->fs_info->commit_root_sem);
}
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index e79ff6b90cb7..2f6d7b13b5bd 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -3066,7 +3066,7 @@ process_slot:
new_key.offset + datal,
1);
if (ret) {
- if (ret != -EINVAL)
+ if (ret != -EOPNOTSUPP)
btrfs_abort_transaction(trans,
root, ret);
btrfs_end_transaction(trans, root);
@@ -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,12 +3138,14 @@ 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 != -EINVAL)
+ if (ret != -EOPNOTSUPP)
btrfs_abort_transaction(trans,
root, ret);
btrfs_end_transaction(trans, root);
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index 1ac3ca98c429..fd38b5053479 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -349,6 +349,11 @@ static int fs_path_ensure_buf(struct fs_path *p, int len)
if (p->buf_len >= len)
return 0;
+ if (len > PATH_MAX) {
+ WARN_ON(1);
+ return -ENOMEM;
+ }
+
path_len = p->end - p->start;
old_buf_len = p->buf_len;
@@ -1663,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);
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 5011aadacab8..9601d25a4607 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -385,20 +385,6 @@ static match_table_t tokens = {
{Opt_err, NULL},
};
-#define btrfs_set_and_info(root, opt, fmt, args...) \
-{ \
- if (!btrfs_test_opt(root, opt)) \
- btrfs_info(root->fs_info, fmt, ##args); \
- btrfs_set_opt(root->fs_info->mount_opt, opt); \
-}
-
-#define btrfs_clear_and_info(root, opt, fmt, args...) \
-{ \
- if (btrfs_test_opt(root, opt)) \
- btrfs_info(root->fs_info, fmt, ##args); \
- btrfs_clear_opt(root->fs_info->mount_opt, opt); \
-}
-
/*
* Regular mount options parser. Everything that is needed only when
* reading in a new superblock is parsed here.
@@ -1186,7 +1172,6 @@ static struct dentry *mount_subvol(const char *subvol_name, int flags,
return ERR_PTR(-ENOMEM);
mnt = vfs_kern_mount(&btrfs_fs_type, flags, device_name,
newargs);
- kfree(newargs);
if (PTR_RET(mnt) == -EBUSY) {
if (flags & MS_RDONLY) {
@@ -1196,17 +1181,22 @@ static struct dentry *mount_subvol(const char *subvol_name, int flags,
int r;
mnt = vfs_kern_mount(&btrfs_fs_type, flags | MS_RDONLY, device_name,
newargs);
- if (IS_ERR(mnt))
+ if (IS_ERR(mnt)) {
+ kfree(newargs);
return ERR_CAST(mnt);
+ }
r = btrfs_remount(mnt->mnt_sb, &flags, NULL);
if (r < 0) {
/* FIXME: release vfsmount mnt ??*/
+ kfree(newargs);
return ERR_PTR(r);
}
}
}
+ kfree(newargs);
+
if (IS_ERR(mnt))
return ERR_CAST(mnt);
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index 2e5e648eb5c3..c561b628ebce 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -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;
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index 766410a12c2c..c29d6ae68874 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -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;
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 39da1c2efa50..88a6df4cbe6d 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -1221,9 +1221,6 @@ static long ceph_fallocate(struct file *file, int mode,
if (!S_ISREG(inode->i_mode))
return -EOPNOTSUPP;
- if (IS_SWAPFILE(inode))
- return -ETXTBSY;
-
mutex_lock(&inode->i_mutex);
if (ceph_snap(inode) != CEPH_NOSNAP) {
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 0b0728e5be2d..233c6f96910a 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -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 */
@@ -890,41 +889,6 @@ out_unlock:
}
/*
- * 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;
diff --git a/fs/ceph/ioctl.c b/fs/ceph/ioctl.c
index fdf941b44ff1..a822a6e58290 100644
--- a/fs/ceph/ioctl.c
+++ b/fs/ceph/ioctl.c
@@ -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);
diff --git a/fs/ceph/locks.c b/fs/ceph/locks.c
index d94ba0df9f4d..191398852a2e 100644
--- a/fs/ceph/locks.c
+++ b/fs/ceph/locks.c
@@ -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)
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 7866cd05a6bb..ead05cc1f447 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -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;
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index df9c9141c099..5be1f997ecde 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -253,6 +253,11 @@ cifs_alloc_inode(struct super_block *sb)
cifs_set_oplock_level(cifs_inode, 0);
cifs_inode->delete_pending = false;
cifs_inode->invalid_mapping = false;
+ clear_bit(CIFS_INODE_PENDING_OPLOCK_BREAK, &cifs_inode->flags);
+ clear_bit(CIFS_INODE_PENDING_WRITERS, &cifs_inode->flags);
+ clear_bit(CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2, &cifs_inode->flags);
+ spin_lock_init(&cifs_inode->writers_lock);
+ cifs_inode->writers = 0;
cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
cifs_inode->server_eof = 0;
cifs_inode->uniqueid = 0;
@@ -732,19 +737,26 @@ static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t pos)
{
struct inode *inode = file_inode(iocb->ki_filp);
+ struct cifsInodeInfo *cinode = CIFS_I(inode);
ssize_t written;
int rc;
+ written = cifs_get_writer(cinode);
+ if (written)
+ return written;
+
written = generic_file_aio_write(iocb, iov, nr_segs, pos);
if (CIFS_CACHE_WRITE(CIFS_I(inode)))
- return written;
+ goto out;
rc = filemap_fdatawrite(inode->i_mapping);
if (rc)
cifs_dbg(FYI, "cifs_file_aio_write: %d rc on %p inode\n",
rc, inode);
+out:
+ cifs_put_writer(cinode);
return written;
}
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index c0f3718b77a8..30f6e9251a4a 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -228,6 +228,8 @@ struct smb_version_operations {
/* verify the message */
int (*check_message)(char *, unsigned int);
bool (*is_oplock_break)(char *, struct TCP_Server_Info *);
+ void (*downgrade_oplock)(struct TCP_Server_Info *,
+ struct cifsInodeInfo *, bool);
/* process transaction2 response */
bool (*check_trans2)(struct mid_q_entry *, struct TCP_Server_Info *,
char *, int);
@@ -1113,6 +1115,12 @@ struct cifsInodeInfo {
unsigned int epoch; /* used to track lease state changes */
bool delete_pending; /* DELETE_ON_CLOSE is set */
bool invalid_mapping; /* pagecache is invalid */
+ unsigned long flags;
+#define CIFS_INODE_PENDING_OPLOCK_BREAK (0) /* oplock break in progress */
+#define CIFS_INODE_PENDING_WRITERS (1) /* Writes in progress */
+#define CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2 (2) /* Downgrade oplock to L2 */
+ spinlock_t writers_lock;
+ unsigned int writers; /* Number of writers on this inode */
unsigned long time; /* jiffies of last update of inode */
u64 server_eof; /* current file size on server -- protected by i_lock */
u64 uniqueid; /* server inode number */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index acc4ee8ed075..ca7980a1e303 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -127,6 +127,9 @@ extern u64 cifs_UnixTimeToNT(struct timespec);
extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time,
int offset);
extern void cifs_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock);
+extern int cifs_get_writer(struct cifsInodeInfo *cinode);
+extern void cifs_put_writer(struct cifsInodeInfo *cinode);
+extern void cifs_done_oplock_break(struct cifsInodeInfo *cinode);
extern int cifs_unlock_range(struct cifsFileInfo *cfile,
struct file_lock *flock, const unsigned int xid);
extern int cifs_push_mandatory_locks(struct cifsFileInfo *cfile);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index f3264bd7a83d..6ce4e0954b98 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -6197,6 +6197,9 @@ QAllEAsRetry:
cifs_dbg(FYI, "ea length %d\n", list_len);
if (list_len <= 8) {
cifs_dbg(FYI, "empty EA list returned from server\n");
+ /* didn't find the named attribute */
+ if (ea_name)
+ rc = -ENODATA;
goto QAllEAsOut;
}
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 8add25538a3b..5ed03e0b8b40 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -2599,7 +2599,7 @@ cifs_writev(struct kiocb *iocb, const struct iovec *iov,
ssize_t err;
err = generic_write_sync(file, iocb->ki_pos - rc, rc);
- if (rc < 0)
+ if (err < 0)
rc = err;
}
} else {
@@ -2621,12 +2621,20 @@ cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov,
struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
ssize_t written;
+ written = cifs_get_writer(cinode);
+ if (written)
+ return written;
+
if (CIFS_CACHE_WRITE(cinode)) {
if (cap_unix(tcon->ses) &&
(CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability))
- && ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
- return generic_file_aio_write(iocb, iov, nr_segs, pos);
- return cifs_writev(iocb, iov, nr_segs, pos);
+ && ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) {
+ written = generic_file_aio_write(
+ iocb, iov, nr_segs, pos);
+ goto out;
+ }
+ written = cifs_writev(iocb, iov, nr_segs, pos);
+ goto out;
}
/*
* For non-oplocked files in strict cache mode we need to write the data
@@ -2646,6 +2654,8 @@ cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov,
inode);
cinode->oplock = 0;
}
+out:
+ cifs_put_writer(cinode);
return written;
}
@@ -2872,7 +2882,7 @@ ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov,
cifs_uncached_readv_complete);
if (!rdata) {
rc = -ENOMEM;
- goto error;
+ break;
}
rc = cifs_read_allocate_pages(rdata, npages);
@@ -3621,6 +3631,13 @@ static int cifs_launder_page(struct page *page)
return rc;
}
+static int
+cifs_pending_writers_wait(void *unused)
+{
+ schedule();
+ return 0;
+}
+
void cifs_oplock_break(struct work_struct *work)
{
struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
@@ -3628,8 +3645,15 @@ void cifs_oplock_break(struct work_struct *work)
struct inode *inode = cfile->dentry->d_inode;
struct cifsInodeInfo *cinode = CIFS_I(inode);
struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
+ struct TCP_Server_Info *server = tcon->ses->server;
int rc = 0;
+ wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS,
+ cifs_pending_writers_wait, TASK_UNINTERRUPTIBLE);
+
+ server->ops->downgrade_oplock(server, cinode,
+ test_bit(CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2, &cinode->flags));
+
if (!CIFS_CACHE_WRITE(cinode) && CIFS_CACHE_READ(cinode) &&
cifs_has_mand_locks(cinode)) {
cifs_dbg(FYI, "Reset oplock to None for inode=%p due to mand locks\n",
@@ -3666,6 +3690,7 @@ void cifs_oplock_break(struct work_struct *work)
cinode);
cifs_dbg(FYI, "Oplock release rc = %d\n", rc);
}
+ cifs_done_oplock_break(cinode);
}
/*
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index aadc2b68678b..a22d667f1069 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -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;
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 2f9f3790679d..3b0c62e622da 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -466,8 +466,22 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
cifs_dbg(FYI, "file id match, oplock break\n");
pCifsInode = CIFS_I(netfile->dentry->d_inode);
- cifs_set_oplock_level(pCifsInode,
- pSMB->OplockLevel ? OPLOCK_READ : 0);
+ set_bit(CIFS_INODE_PENDING_OPLOCK_BREAK,
+ &pCifsInode->flags);
+
+ /*
+ * Set flag if the server downgrades the oplock
+ * to L2 else clear.
+ */
+ if (pSMB->OplockLevel)
+ set_bit(
+ CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2,
+ &pCifsInode->flags);
+ else
+ clear_bit(
+ CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2,
+ &pCifsInode->flags);
+
queue_work(cifsiod_wq,
&netfile->oplock_break);
netfile->oplock_break_cancelled = false;
@@ -551,6 +565,62 @@ void cifs_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock)
cinode->oplock = 0;
}
+static int
+cifs_oplock_break_wait(void *unused)
+{
+ schedule();
+ return signal_pending(current) ? -ERESTARTSYS : 0;
+}
+
+/*
+ * We wait for oplock breaks to be processed before we attempt to perform
+ * writes.
+ */
+int cifs_get_writer(struct cifsInodeInfo *cinode)
+{
+ int rc;
+
+start:
+ rc = wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_OPLOCK_BREAK,
+ cifs_oplock_break_wait, TASK_KILLABLE);
+ if (rc)
+ return rc;
+
+ spin_lock(&cinode->writers_lock);
+ if (!cinode->writers)
+ set_bit(CIFS_INODE_PENDING_WRITERS, &cinode->flags);
+ cinode->writers++;
+ /* Check to see if we have started servicing an oplock break */
+ if (test_bit(CIFS_INODE_PENDING_OPLOCK_BREAK, &cinode->flags)) {
+ cinode->writers--;
+ if (cinode->writers == 0) {
+ clear_bit(CIFS_INODE_PENDING_WRITERS, &cinode->flags);
+ wake_up_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS);
+ }
+ spin_unlock(&cinode->writers_lock);
+ goto start;
+ }
+ spin_unlock(&cinode->writers_lock);
+ return 0;
+}
+
+void cifs_put_writer(struct cifsInodeInfo *cinode)
+{
+ spin_lock(&cinode->writers_lock);
+ cinode->writers--;
+ if (cinode->writers == 0) {
+ clear_bit(CIFS_INODE_PENDING_WRITERS, &cinode->flags);
+ wake_up_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS);
+ }
+ spin_unlock(&cinode->writers_lock);
+}
+
+void cifs_done_oplock_break(struct cifsInodeInfo *cinode)
+{
+ clear_bit(CIFS_INODE_PENDING_OPLOCK_BREAK, &cinode->flags);
+ wake_up_bit(&cinode->flags, CIFS_INODE_PENDING_OPLOCK_BREAK);
+}
+
bool
backup_cred(struct cifs_sb_info *cifs_sb)
{
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index 526fb89f9230..d1fdfa848703 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -372,6 +372,16 @@ coalesce_t2(char *second_buf, struct smb_hdr *target_hdr)
return 0;
}
+static void
+cifs_downgrade_oplock(struct TCP_Server_Info *server,
+ struct cifsInodeInfo *cinode, bool set_level2)
+{
+ if (set_level2)
+ cifs_set_oplock_level(cinode, OPLOCK_READ);
+ else
+ cifs_set_oplock_level(cinode, 0);
+}
+
static bool
cifs_check_trans2(struct mid_q_entry *mid, struct TCP_Server_Info *server,
char *buf, int malformed)
@@ -1019,6 +1029,7 @@ struct smb_version_operations smb1_operations = {
.clear_stats = cifs_clear_stats,
.print_stats = cifs_print_stats,
.is_oplock_break = is_valid_oplock_break,
+ .downgrade_oplock = cifs_downgrade_oplock,
.check_trans2 = cifs_check_trans2,
.need_neg = cifs_need_neg,
.negotiate = cifs_negotiate,
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
index fb3966265b6e..b8021fde987d 100644
--- a/fs/cifs/smb2misc.c
+++ b/fs/cifs/smb2misc.c
@@ -575,9 +575,21 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
else
cfile->oplock_break_cancelled = false;
- server->ops->set_oplock_level(cinode,
- rsp->OplockLevel ? SMB2_OPLOCK_LEVEL_II : 0,
- 0, NULL);
+ set_bit(CIFS_INODE_PENDING_OPLOCK_BREAK,
+ &cinode->flags);
+
+ /*
+ * Set flag if the server downgrades the oplock
+ * to L2 else clear.
+ */
+ if (rsp->OplockLevel)
+ set_bit(
+ CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2,
+ &cinode->flags);
+ else
+ clear_bit(
+ CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2,
+ &cinode->flags);
queue_work(cifsiod_wq, &cfile->oplock_break);
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 192f51a12cf1..35ddc3ed119d 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -905,6 +905,17 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
}
static void
+smb2_downgrade_oplock(struct TCP_Server_Info *server,
+ struct cifsInodeInfo *cinode, bool set_level2)
+{
+ if (set_level2)
+ server->ops->set_oplock_level(cinode, SMB2_OPLOCK_LEVEL_II,
+ 0, NULL);
+ else
+ server->ops->set_oplock_level(cinode, 0, 0, NULL);
+}
+
+static void
smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
unsigned int epoch, bool *purge_cache)
{
@@ -1110,6 +1121,7 @@ struct smb_version_operations smb20_operations = {
.clear_stats = smb2_clear_stats,
.print_stats = smb2_print_stats,
.is_oplock_break = smb2_is_valid_oplock_break,
+ .downgrade_oplock = smb2_downgrade_oplock,
.need_neg = smb2_need_neg,
.negotiate = smb2_negotiate,
.negotiate_wsize = smb2_negotiate_wsize,
@@ -1184,6 +1196,7 @@ struct smb_version_operations smb21_operations = {
.clear_stats = smb2_clear_stats,
.print_stats = smb2_print_stats,
.is_oplock_break = smb2_is_valid_oplock_break,
+ .downgrade_oplock = smb2_downgrade_oplock,
.need_neg = smb2_need_neg,
.negotiate = smb2_negotiate,
.negotiate_wsize = smb2_negotiate_wsize,
@@ -1259,6 +1272,7 @@ struct smb_version_operations smb30_operations = {
.print_stats = smb2_print_stats,
.dump_share_caps = smb2_dump_share_caps,
.is_oplock_break = smb2_is_valid_oplock_break,
+ .downgrade_oplock = smb2_downgrade_oplock,
.need_neg = smb2_need_neg,
.negotiate = smb2_negotiate,
.negotiate_wsize = smb2_negotiate_wsize,
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 860344701067..3802f8c94acc 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -1352,7 +1352,6 @@ SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_fid, u64 volatile_fid)
{
int rc;
- char *res_key = NULL;
struct compress_ioctl fsctl_input;
char *ret_data = NULL;
@@ -1365,7 +1364,6 @@ SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
2 /* in data len */, &ret_data /* out data */, NULL);
cifs_dbg(FYI, "set compression rc %d\n", rc);
- kfree(res_key);
return rc;
}
diff --git a/fs/compat.c b/fs/compat.c
index ca926ad0430c..66d3d3c6b4b2 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -457,9 +457,9 @@ COMPAT_SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd,
case F_GETLK64:
case F_SETLK64:
case F_SETLKW64:
- case F_GETLKP:
- case F_SETLKP:
- case F_SETLKPW:
+ case F_OFD_GETLK:
+ case F_OFD_SETLK:
+ case F_OFD_SETLKW:
ret = get_compat_flock64(&f, compat_ptr(arg));
if (ret != 0)
break;
@@ -468,7 +468,7 @@ COMPAT_SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd,
conv_cmd = convert_fcntl_cmd(cmd);
ret = sys_fcntl(fd, conv_cmd, (unsigned long)&f);
set_fs(old_fs);
- if ((conv_cmd == F_GETLK || conv_cmd == F_GETLKP) && ret == 0) {
+ if ((conv_cmd == F_GETLK || conv_cmd == F_OFD_GETLK) && ret == 0) {
/* need to return lock information - see above for commentary */
if (f.l_start > COMPAT_LOFF_T_MAX)
ret = -EOVERFLOW;
@@ -493,9 +493,9 @@ COMPAT_SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd,
case F_GETLK64:
case F_SETLK64:
case F_SETLKW64:
- case F_GETLKP:
- case F_SETLKP:
- case F_SETLKPW:
+ case F_OFD_GETLK:
+ case F_OFD_SETLK:
+ case F_OFD_SETLKW:
return -EINVAL;
}
return compat_sys_fcntl64(fd, cmd, arg);
diff --git a/fs/coredump.c b/fs/coredump.c
index e3ad709a4232..0b2528fb640e 100644
--- a/fs/coredump.c
+++ b/fs/coredump.c
@@ -73,10 +73,15 @@ static int expand_corename(struct core_name *cn, int size)
static int cn_vprintf(struct core_name *cn, const char *fmt, va_list arg)
{
int free, need;
+ va_list arg_copy;
again:
free = cn->size - cn->used;
- need = vsnprintf(cn->corename + cn->used, free, fmt, arg);
+
+ va_copy(arg_copy, arg);
+ need = vsnprintf(cn->corename + cn->used, free, fmt, arg_copy);
+ va_end(arg_copy);
+
if (need < free) {
cn->used += need;
return 0;
diff --git a/fs/dcache.c b/fs/dcache.c
index 40707d88a945..be2bea834bf4 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -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;
diff --git a/fs/exec.c b/fs/exec.c
index 476f3ebf437e..238b7aa26f68 100644
--- 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)
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 6ea7b1436bbc..5c56785007e0 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -667,7 +667,7 @@ ext4_fsblk_t ext4_count_free_clusters(struct super_block *sb)
continue;
x = ext4_count_free(bitmap_bh->b_data,
- EXT4_BLOCKS_PER_GROUP(sb) / 8);
+ EXT4_CLUSTERS_PER_GROUP(sb) / 8);
printk(KERN_DEBUG "group %u: stored = %d, counted = %u\n",
i, ext4_free_group_clusters(sb, gdp), x);
bitmap_count += x;
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index f1c65dc7cc0a..66946aa62127 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2466,23 +2466,6 @@ static inline void ext4_update_i_disksize(struct inode *inode, loff_t newsize)
up_write(&EXT4_I(inode)->i_data_sem);
}
-/*
- * Update i_disksize after writeback has been started. Races with truncate
- * are avoided by checking i_size under i_data_sem.
- */
-static inline void ext4_wb_update_i_disksize(struct inode *inode, loff_t newsize)
-{
- loff_t i_size;
-
- down_write(&EXT4_I(inode)->i_data_sem);
- i_size = i_size_read(inode);
- if (newsize > i_size)
- newsize = i_size;
- if (newsize > EXT4_I(inode)->i_disksize)
- EXT4_I(inode)->i_disksize = newsize;
- up_write(&EXT4_I(inode)->i_data_sem);
-}
-
struct ext4_group_info {
unsigned long bb_state;
struct rb_root bb_free_root;
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 82df3ce9874a..01b0c208f625 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -3313,6 +3313,11 @@ static int ext4_split_extent(handle_t *handle,
return PTR_ERR(path);
depth = ext_depth(inode);
ex = path[depth].p_ext;
+ if (!ex) {
+ EXT4_ERROR_INODE(inode, "unexpected hole at %lu",
+ (unsigned long) map->m_lblk);
+ return -EIO;
+ }
uninitialized = ext4_ext_is_uninitialized(ex);
split_flag1 = 0;
@@ -3694,6 +3699,12 @@ static int ext4_convert_initialized_extents(handle_t *handle,
}
depth = ext_depth(inode);
ex = path[depth].p_ext;
+ if (!ex) {
+ EXT4_ERROR_INODE(inode, "unexpected hole at %lu",
+ (unsigned long) map->m_lblk);
+ err = -EIO;
+ goto out;
+ }
}
err = ext4_ext_get_access(handle, inode, path + depth);
@@ -4730,6 +4741,9 @@ static long ext4_zero_range(struct file *file, loff_t offset,
trace_ext4_zero_range(inode, offset, len, mode);
+ if (!S_ISREG(inode->i_mode))
+ return -EINVAL;
+
/*
* Write out all dirty pages to avoid race conditions
* Then release them.
@@ -4878,9 +4892,6 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
if (mode & FALLOC_FL_PUNCH_HOLE)
return ext4_punch_hole(inode, offset, len);
- if (mode & FALLOC_FL_COLLAPSE_RANGE)
- return ext4_collapse_range(inode, offset, len);
-
ret = ext4_convert_inline_data(inode);
if (ret)
return ret;
@@ -4892,6 +4903,9 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
return -EOPNOTSUPP;
+ if (mode & FALLOC_FL_COLLAPSE_RANGE)
+ return ext4_collapse_range(inode, offset, len);
+
if (mode & FALLOC_FL_ZERO_RANGE)
return ext4_zero_range(file, offset, len, mode);
@@ -5229,18 +5243,19 @@ ext4_ext_shift_path_extents(struct ext4_ext_path *path, ext4_lblk_t shift,
if (ex_start == EXT_FIRST_EXTENT(path[depth].p_hdr))
update = 1;
- *start = ex_last->ee_block +
+ *start = le32_to_cpu(ex_last->ee_block) +
ext4_ext_get_actual_len(ex_last);
while (ex_start <= ex_last) {
- ex_start->ee_block -= shift;
- if (ex_start >
- EXT_FIRST_EXTENT(path[depth].p_hdr)) {
- if (ext4_ext_try_to_merge_right(inode,
- path, ex_start - 1))
- ex_last--;
- }
- ex_start++;
+ le32_add_cpu(&ex_start->ee_block, -shift);
+ /* Try to merge to the left. */
+ if ((ex_start >
+ EXT_FIRST_EXTENT(path[depth].p_hdr)) &&
+ ext4_ext_try_to_merge_right(inode,
+ path, ex_start - 1))
+ ex_last--;
+ else
+ ex_start++;
}
err = ext4_ext_dirty(handle, inode, path + depth);
if (err)
@@ -5255,7 +5270,7 @@ ext4_ext_shift_path_extents(struct ext4_ext_path *path, ext4_lblk_t shift,
if (err)
goto out;
- path[depth].p_idx->ei_block -= shift;
+ le32_add_cpu(&path[depth].p_idx->ei_block, -shift);
err = ext4_ext_dirty(handle, inode, path + depth);
if (err)
goto out;
@@ -5300,7 +5315,8 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
return ret;
}
- stop_block = extent->ee_block + ext4_ext_get_actual_len(extent);
+ stop_block = le32_to_cpu(extent->ee_block) +
+ ext4_ext_get_actual_len(extent);
ext4_ext_drop_refs(path);
kfree(path);
@@ -5313,10 +5329,18 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
* enough to accomodate the shift.
*/
path = ext4_ext_find_extent(inode, start - 1, NULL, 0);
+ if (IS_ERR(path))
+ return PTR_ERR(path);
depth = path->p_depth;
extent = path[depth].p_ext;
- ex_start = extent->ee_block;
- ex_end = extent->ee_block + ext4_ext_get_actual_len(extent);
+ if (extent) {
+ ex_start = le32_to_cpu(extent->ee_block);
+ ex_end = le32_to_cpu(extent->ee_block) +
+ ext4_ext_get_actual_len(extent);
+ } else {
+ ex_start = 0;
+ ex_end = 0;
+ }
ext4_ext_drop_refs(path);
kfree(path);
@@ -5331,7 +5355,13 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
return PTR_ERR(path);
depth = path->p_depth;
extent = path[depth].p_ext;
- current_block = extent->ee_block;
+ if (!extent) {
+ EXT4_ERROR_INODE(inode, "unexpected hole at %lu",
+ (unsigned long) start);
+ return -EIO;
+ }
+
+ current_block = le32_to_cpu(extent->ee_block);
if (start > current_block) {
/* Hole, move to the next extent */
ret = mext_next_extent(inode, path, &extent);
@@ -5365,17 +5395,18 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
ext4_lblk_t punch_start, punch_stop;
handle_t *handle;
unsigned int credits;
- loff_t new_size;
+ loff_t new_size, ioffset;
int ret;
- BUG_ON(offset + len > i_size_read(inode));
-
/* Collapse range works only on fs block size aligned offsets. */
if (offset & (EXT4_BLOCK_SIZE(sb) - 1) ||
len & (EXT4_BLOCK_SIZE(sb) - 1))
return -EINVAL;
if (!S_ISREG(inode->i_mode))
+ return -EINVAL;
+
+ if (EXT4_SB(inode->i_sb)->s_cluster_ratio > 1)
return -EOPNOTSUPP;
trace_ext4_collapse_range(inode, offset, len);
@@ -5383,22 +5414,34 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
punch_start = offset >> EXT4_BLOCK_SIZE_BITS(sb);
punch_stop = (offset + len) >> EXT4_BLOCK_SIZE_BITS(sb);
+ /* Call ext4_force_commit to flush all data in case of data=journal. */
+ if (ext4_should_journal_data(inode)) {
+ ret = ext4_force_commit(inode->i_sb);
+ if (ret)
+ return ret;
+ }
+
+ /*
+ * Need to round down offset to be aligned with page size boundary
+ * for page size > block size.
+ */
+ ioffset = round_down(offset, PAGE_SIZE);
+
/* Write out all dirty pages */
- ret = filemap_write_and_wait_range(inode->i_mapping, offset, -1);
+ ret = filemap_write_and_wait_range(inode->i_mapping, ioffset,
+ LLONG_MAX);
if (ret)
return ret;
/* Take mutex lock */
mutex_lock(&inode->i_mutex);
- /* It's not possible punch hole on append only file */
- if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) {
- ret = -EPERM;
- goto out_mutex;
- }
-
- if (IS_SWAPFILE(inode)) {
- ret = -ETXTBSY;
+ /*
+ * There is no need to overlap collapse range with EOF, in which case
+ * it is effectively a truncate operation
+ */
+ if (offset + len >= i_size_read(inode)) {
+ ret = -EINVAL;
goto out_mutex;
}
@@ -5408,7 +5451,7 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
goto out_mutex;
}
- truncate_pagecache_range(inode, offset, -1);
+ truncate_pagecache(inode, ioffset);
/* Wait for existing dio to complete */
ext4_inode_block_unlocked_dio(inode);
@@ -5425,7 +5468,7 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
ext4_discard_preallocations(inode);
ret = ext4_es_remove_extent(inode, punch_start,
- EXT_MAX_BLOCKS - punch_start - 1);
+ EXT_MAX_BLOCKS - punch_start);
if (ret) {
up_write(&EXT4_I(inode)->i_data_sem);
goto out_stop;
@@ -5436,6 +5479,7 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
up_write(&EXT4_I(inode)->i_data_sem);
goto out_stop;
}
+ ext4_discard_preallocations(inode);
ret = ext4_ext_shift_extents(inode, handle, punch_stop,
punch_stop - punch_start);
@@ -5445,10 +5489,9 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
}
new_size = i_size_read(inode) - len;
- truncate_setsize(inode, new_size);
+ i_size_write(inode, new_size);
EXT4_I(inode)->i_disksize = new_size;
- ext4_discard_preallocations(inode);
up_write(&EXT4_I(inode)->i_data_sem);
if (IS_SYNC(inode))
ext4_handle_sync(handle);
diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
index 0a014a7194b2..0ebc21204b51 100644
--- a/fs/ext4/extents_status.c
+++ b/fs/ext4/extents_status.c
@@ -810,7 +810,7 @@ retry:
newes.es_lblk = end + 1;
newes.es_len = len2;
- block = 0x7FDEADBEEF;
+ block = 0x7FDEADBEEFULL;
if (ext4_es_is_written(&orig_es) ||
ext4_es_is_unwritten(&orig_es))
block = ext4_es_pblock(&orig_es) +
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index ca7502d89fde..063fc1538355 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -82,7 +82,7 @@ ext4_unaligned_aio(struct inode *inode, const struct iovec *iov,
size_t count = iov_length(iov, nr_segs);
loff_t final_size = pos + count;
- if (pos >= inode->i_size)
+ if (pos >= i_size_read(inode))
return 0;
if ((pos & blockmask) || (final_size & blockmask))
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 5b0d2c7d5408..d7b7462a0e13 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -522,6 +522,10 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
if (unlikely(map->m_len > INT_MAX))
map->m_len = INT_MAX;
+ /* We can handle the block number less than EXT_MAX_BLOCKS */
+ if (unlikely(map->m_lblk >= EXT_MAX_BLOCKS))
+ return -EIO;
+
/* Lookup extent status tree firstly */
if (ext4_es_lookup_extent(inode, map->m_lblk, &es)) {
ext4_es_lru_add(inode);
@@ -2243,13 +2247,23 @@ static int mpage_map_and_submit_extent(handle_t *handle,
return err;
} while (map->m_len);
- /* Update on-disk size after IO is submitted */
+ /*
+ * Update on-disk size after IO is submitted. Races with
+ * truncate are avoided by checking i_size under i_data_sem.
+ */
disksize = ((loff_t)mpd->first_page) << PAGE_CACHE_SHIFT;
if (disksize > EXT4_I(inode)->i_disksize) {
int err2;
-
- ext4_wb_update_i_disksize(inode, disksize);
+ loff_t i_size;
+
+ down_write(&EXT4_I(inode)->i_data_sem);
+ i_size = i_size_read(inode);
+ if (disksize > i_size)
+ disksize = i_size;
+ if (disksize > EXT4_I(inode)->i_disksize)
+ EXT4_I(inode)->i_disksize = disksize;
err2 = ext4_mark_inode_dirty(handle, inode);
+ up_write(&EXT4_I(inode)->i_data_sem);
if (err2)
ext4_error(inode->i_sb,
"Failed to mark inode %lu dirty",
@@ -3527,15 +3541,6 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
}
mutex_lock(&inode->i_mutex);
- /* It's not possible punch hole on append only file */
- if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) {
- ret = -EPERM;
- goto out_mutex;
- }
- if (IS_SWAPFILE(inode)) {
- ret = -ETXTBSY;
- goto out_mutex;
- }
/* No need to punch hole beyond i_size */
if (offset >= inode->i_size)
@@ -3616,7 +3621,6 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
ret = ext4_free_hole_blocks(handle, inode, first_block,
stop_block);
- ext4_discard_preallocations(inode);
up_write(&EXT4_I(inode)->i_data_sem);
if (IS_SYNC(inode))
ext4_handle_sync(handle);
@@ -4423,21 +4427,20 @@ out_brelse:
*
* We are called from a few places:
*
- * - Within generic_file_write() for O_SYNC files.
+ * - Within generic_file_aio_write() -> generic_write_sync() for O_SYNC files.
* Here, there will be no transaction running. We wait for any running
* transaction to commit.
*
- * - Within sys_sync(), kupdate and such.
- * We wait on commit, if tol to.
+ * - Within flush work (sys_sync(), kupdate and such).
+ * We wait on commit, if told to.
*
- * - Within prune_icache() (PF_MEMALLOC == true)
- * Here we simply return. We can't afford to block kswapd on the
- * journal commit.
+ * - Within iput_final() -> write_inode_now()
+ * We wait on commit, if told to.
*
* In all cases it is actually safe for us to return without doing anything,
* because the inode has been copied into a raw inode buffer in
- * ext4_mark_inode_dirty(). This is a correctness thing for O_SYNC and for
- * knfsd.
+ * ext4_mark_inode_dirty(). This is a correctness thing for WB_SYNC_ALL
+ * writeback.
*
* Note that we are absolutely dependent upon all inode dirtiers doing the
* right thing: they *must* call mark_inode_dirty() after dirtying info in
@@ -4449,15 +4452,15 @@ out_brelse:
* stuff();
* inode->i_size = expr;
*
- * is in error because a kswapd-driven write_inode() could occur while
- * `stuff()' is running, and the new i_size will be lost. Plus the inode
- * will no longer be on the superblock's dirty inode list.
+ * is in error because write_inode() could occur while `stuff()' is running,
+ * and the new i_size will be lost. Plus the inode will no longer be on the
+ * superblock's dirty inode list.
*/
int ext4_write_inode(struct inode *inode, struct writeback_control *wbc)
{
int err;
- if (current->flags & PF_MEMALLOC)
+ if (WARN_ON_ONCE(current->flags & PF_MEMALLOC))
return 0;
if (EXT4_SB(inode->i_sb)->s_journal) {
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index a888cac76e9c..c8238a26818c 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -989,7 +989,7 @@ static int ext4_mb_get_buddy_page_lock(struct super_block *sb,
poff = block % blocks_per_page;
page = find_or_create_page(inode->i_mapping, pnum, GFP_NOFS);
if (!page)
- return -EIO;
+ return -ENOMEM;
BUG_ON(page->mapping != inode->i_mapping);
e4b->bd_bitmap_page = page;
e4b->bd_bitmap = page_address(page) + (poff * sb->s_blocksize);
@@ -1003,7 +1003,7 @@ static int ext4_mb_get_buddy_page_lock(struct super_block *sb,
pnum = block / blocks_per_page;
page = find_or_create_page(inode->i_mapping, pnum, GFP_NOFS);
if (!page)
- return -EIO;
+ return -ENOMEM;
BUG_ON(page->mapping != inode->i_mapping);
e4b->bd_buddy_page = page;
return 0;
@@ -1168,7 +1168,11 @@ ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group,
unlock_page(page);
}
}
- if (page == NULL || !PageUptodate(page)) {
+ if (page == NULL) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ if (!PageUptodate(page)) {
ret = -EIO;
goto err;
}
@@ -1197,7 +1201,11 @@ ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group,
unlock_page(page);
}
}
- if (page == NULL || !PageUptodate(page)) {
+ if (page == NULL) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ if (!PageUptodate(page)) {
ret = -EIO;
goto err;
}
@@ -5008,6 +5016,8 @@ error_return:
*/
static int ext4_trim_extent(struct super_block *sb, int start, int count,
ext4_group_t group, struct ext4_buddy *e4b)
+__releases(bitlock)
+__acquires(bitlock)
{
struct ext4_free_extent ex;
int ret = 0;
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
index ab95508e3d40..c18d95b50540 100644
--- a/fs/ext4/page-io.c
+++ b/fs/ext4/page-io.c
@@ -308,13 +308,14 @@ static void ext4_end_bio(struct bio *bio, int error)
if (error) {
struct inode *inode = io_end->inode;
- ext4_warning(inode->i_sb, "I/O error writing to inode %lu "
+ ext4_warning(inode->i_sb, "I/O error %d writing to inode %lu "
"(offset %llu size %ld starting block %llu)",
- inode->i_ino,
+ error, inode->i_ino,
(unsigned long long) io_end->offset,
(long) io_end->size,
(unsigned long long)
bi_sector >> (inode->i_blkbits - 9));
+ mapping_set_error(inode->i_mapping, error);
}
if (io_end->flag & EXT4_IO_END_UNWRITTEN) {
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index f3c667091618..6f9e6fadac04 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -3869,19 +3869,38 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
goto failed_mount2;
}
}
+
+ /*
+ * set up enough so that it can read an inode,
+ * and create new inode for buddy allocator
+ */
+ sbi->s_gdb_count = db_count;
+ if (!test_opt(sb, NOLOAD) &&
+ EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL))
+ sb->s_op = &ext4_sops;
+ else
+ sb->s_op = &ext4_nojournal_sops;
+
+ ext4_ext_init(sb);
+ err = ext4_mb_init(sb);
+ if (err) {
+ ext4_msg(sb, KERN_ERR, "failed to initialize mballoc (%d)",
+ err);
+ goto failed_mount2;
+ }
+
if (!ext4_check_descriptors(sb, &first_not_zeroed)) {
ext4_msg(sb, KERN_ERR, "group descriptors corrupted!");
- goto failed_mount2;
+ goto failed_mount2a;
}
if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG))
if (!ext4_fill_flex_info(sb)) {
ext4_msg(sb, KERN_ERR,
"unable to initialize "
"flex_bg meta info!");
- goto failed_mount2;
+ goto failed_mount2a;
}
- sbi->s_gdb_count = db_count;
get_random_bytes(&sbi->s_next_generation, sizeof(u32));
spin_lock_init(&sbi->s_next_gen_lock);
@@ -3916,14 +3935,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
sbi->s_stripe = ext4_get_stripe_size(sbi);
sbi->s_extent_max_zeroout_kb = 32;
- /*
- * set up enough so that it can read an inode
- */
- if (!test_opt(sb, NOLOAD) &&
- EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL))
- sb->s_op = &ext4_sops;
- else
- sb->s_op = &ext4_nojournal_sops;
sb->s_export_op = &ext4_export_ops;
sb->s_xattr = ext4_xattr_handlers;
#ifdef CONFIG_QUOTA
@@ -4113,21 +4124,13 @@ no_journal:
if (err) {
ext4_msg(sb, KERN_ERR, "failed to reserve %llu clusters for "
"reserved pool", ext4_calculate_resv_clusters(sb));
- goto failed_mount4a;
+ goto failed_mount5;
}
err = ext4_setup_system_zone(sb);
if (err) {
ext4_msg(sb, KERN_ERR, "failed to initialize system "
"zone (%d)", err);
- goto failed_mount4a;
- }
-
- ext4_ext_init(sb);
- err = ext4_mb_init(sb);
- if (err) {
- ext4_msg(sb, KERN_ERR, "failed to initialize mballoc (%d)",
- err);
goto failed_mount5;
}
@@ -4204,11 +4207,8 @@ failed_mount8:
failed_mount7:
ext4_unregister_li_request(sb);
failed_mount6:
- ext4_mb_release(sb);
-failed_mount5:
- ext4_ext_release(sb);
ext4_release_system_zone(sb);
-failed_mount4a:
+failed_mount5:
dput(sb->s_root);
sb->s_root = NULL;
failed_mount4:
@@ -4232,11 +4232,14 @@ failed_mount3:
percpu_counter_destroy(&sbi->s_extent_cache_cnt);
if (sbi->s_mmp_tsk)
kthread_stop(sbi->s_mmp_tsk);
+failed_mount2a:
+ ext4_mb_release(sb);
failed_mount2:
for (i = 0; i < db_count; i++)
brelse(sbi->s_group_desc[i]);
ext4_kvfree(sbi->s_group_desc);
failed_mount:
+ ext4_ext_release(sb);
if (sbi->s_chksum_driver)
crypto_free_shash(sbi->s_chksum_driver);
if (sbi->s_proc) {
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index 1f5cf5880718..4eec399ec807 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -520,8 +520,8 @@ static void ext4_xattr_update_super_block(handle_t *handle,
}
/*
- * Release the xattr block BH: If the reference count is > 1, decrement
- * it; otherwise free the block.
+ * Release the xattr block BH: If the reference count is > 1, decrement it;
+ * otherwise free the block.
*/
static void
ext4_xattr_release_block(handle_t *handle, struct inode *inode,
@@ -542,16 +542,31 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode,
if (ce)
mb_cache_entry_free(ce);
get_bh(bh);
+ unlock_buffer(bh);
ext4_free_blocks(handle, inode, bh, 0, 1,
EXT4_FREE_BLOCKS_METADATA |
EXT4_FREE_BLOCKS_FORGET);
- unlock_buffer(bh);
} else {
le32_add_cpu(&BHDR(bh)->h_refcount, -1);
if (ce)
mb_cache_entry_release(ce);
+ /*
+ * Beware of this ugliness: Releasing of xattr block references
+ * from different inodes can race and so we have to protect
+ * from a race where someone else frees the block (and releases
+ * its journal_head) before we are done dirtying the buffer. In
+ * nojournal mode this race is harmless and we actually cannot
+ * call ext4_handle_dirty_xattr_block() with locked buffer as
+ * that function can call sync_dirty_buffer() so for that case
+ * we handle the dirtying after unlocking the buffer.
+ */
+ if (ext4_handle_valid(handle))
+ error = ext4_handle_dirty_xattr_block(handle, inode,
+ bh);
unlock_buffer(bh);
- error = ext4_handle_dirty_xattr_block(handle, inode, bh);
+ if (!ext4_handle_valid(handle))
+ error = ext4_handle_dirty_xattr_block(handle, inode,
+ bh);
if (IS_SYNC(inode))
ext4_handle_sync(handle);
dquot_free_block(inode, EXT4_C2B(EXT4_SB(inode->i_sb), 1));
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 9ead1596399a..72c82f69b01b 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -274,15 +274,15 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg,
break;
#if BITS_PER_LONG != 32
/* 32-bit arches must use fcntl64() */
- case F_GETLKP:
+ case F_OFD_GETLK:
#endif
case F_GETLK:
err = fcntl_getlk(filp, cmd, (struct flock __user *) arg);
break;
#if BITS_PER_LONG != 32
/* 32-bit arches must use fcntl64() */
- case F_SETLKP:
- case F_SETLKPW:
+ case F_OFD_SETLK:
+ case F_OFD_SETLKW:
#endif
/* Fallthrough */
case F_SETLK:
@@ -399,13 +399,13 @@ SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd,
switch (cmd) {
case F_GETLK64:
- case F_GETLKP:
+ case F_OFD_GETLK:
err = fcntl_getlk64(f.file, cmd, (struct flock64 __user *) arg);
break;
case F_SETLK64:
case F_SETLKW64:
- case F_SETLKP:
- case F_SETLKPW:
+ case F_OFD_SETLK:
+ case F_OFD_SETLKW:
err = fcntl_setlk64(fd, f.file, cmd,
(struct flock64 __user *) arg);
break;
diff --git a/fs/fuse/control.c b/fs/fuse/control.c
index a0b0855d00a9..205e0d5d5307 100644
--- a/fs/fuse/control.c
+++ b/fs/fuse/control.c
@@ -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);
}
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 5b4e035b364c..42198359fa1b 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -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 = {
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 13f8bdec5110..96d513e01a5d 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -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)
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index a257ed8ebee6..7aa5c75e0de1 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -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);
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 8d611696fcad..754dcf23de8a 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -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;
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 204027520937..e19d4c0cacae 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -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;
diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
index 78f3403300af..ac127cd008bf 100644
--- a/fs/kernfs/dir.c
+++ b/fs/kernfs/dir.c
@@ -232,9 +232,6 @@ static int kernfs_link_sibling(struct kernfs_node *kn)
struct rb_node **node = &kn->parent->dir.children.rb_node;
struct rb_node *parent = NULL;
- if (kernfs_type(kn) == KERNFS_DIR)
- kn->parent->dir.subdirs++;
-
while (*node) {
struct kernfs_node *pos;
int result;
@@ -249,9 +246,15 @@ static int kernfs_link_sibling(struct kernfs_node *kn)
else
return -EEXIST;
}
+
/* add new node and rebalance the tree */
rb_link_node(&kn->rb, parent, node);
rb_insert_color(&kn->rb, &kn->parent->dir.children);
+
+ /* successfully added, account subdir number */
+ if (kernfs_type(kn) == KERNFS_DIR)
+ kn->parent->dir.subdirs++;
+
return 0;
}
diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c
index 8034706a7af8..5e9a80cfc3d8 100644
--- a/fs/kernfs/file.c
+++ b/fs/kernfs/file.c
@@ -484,6 +484,8 @@ static int kernfs_fop_mmap(struct file *file, struct vm_area_struct *vma)
ops = kernfs_ops(of->kn);
rc = ops->mmap(of, vma);
+ if (rc)
+ goto out_put;
/*
* PowerPC's pci_mmap of legacy_mem uses shmem_zero_setup()
@@ -608,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;
@@ -622,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;
diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c
index abb0f1f53d93..985217626e66 100644
--- a/fs/kernfs/inode.c
+++ b/fs/kernfs/inode.c
@@ -48,14 +48,18 @@ void __init kernfs_inode_init(void)
static struct kernfs_iattrs *kernfs_iattrs(struct kernfs_node *kn)
{
+ static DEFINE_MUTEX(iattr_mutex);
+ struct kernfs_iattrs *ret;
struct iattr *iattrs;
+ mutex_lock(&iattr_mutex);
+
if (kn->iattr)
- return kn->iattr;
+ goto out_unlock;
kn->iattr = kzalloc(sizeof(struct kernfs_iattrs), GFP_KERNEL);
if (!kn->iattr)
- return NULL;
+ goto out_unlock;
iattrs = &kn->iattr->ia_iattr;
/* assign default attributes */
@@ -65,8 +69,10 @@ static struct kernfs_iattrs *kernfs_iattrs(struct kernfs_node *kn)
iattrs->ia_atime = iattrs->ia_mtime = iattrs->ia_ctime = CURRENT_TIME;
simple_xattrs_init(&kn->iattr->xattrs);
-
- return kn->iattr;
+out_unlock:
+ ret = kn->iattr;
+ mutex_unlock(&iattr_mutex);
+ return ret;
}
static int __kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr)
diff --git a/fs/locks.c b/fs/locks.c
index 13fc7a6d380a..e390bd9ae068 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -135,7 +135,7 @@
#define IS_POSIX(fl) (fl->fl_flags & FL_POSIX)
#define IS_FLOCK(fl) (fl->fl_flags & FL_FLOCK)
#define IS_LEASE(fl) (fl->fl_flags & (FL_LEASE|FL_DELEG))
-#define IS_FILE_PVT(fl) (fl->fl_flags & FL_FILE_PVT)
+#define IS_OFDLCK(fl) (fl->fl_flags & FL_OFDLCK)
static bool lease_breaking(struct file_lock *fl)
{
@@ -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);
}
@@ -564,7 +552,7 @@ static void __locks_insert_block(struct file_lock *blocker,
BUG_ON(!list_empty(&waiter->fl_block));
waiter->fl_next = blocker;
list_add_tail(&waiter->fl_block, &blocker->fl_block);
- if (IS_POSIX(blocker) && !IS_FILE_PVT(blocker))
+ if (IS_POSIX(blocker) && !IS_OFDLCK(blocker))
locks_insert_global_blocked(waiter);
}
@@ -759,12 +747,12 @@ EXPORT_SYMBOL(posix_test_lock);
* of tasks (such as posix threads) sharing the same open file table.
* To handle those cases, we just bail out after a few iterations.
*
- * For FL_FILE_PVT locks, the owner is the filp, not the files_struct.
+ * For FL_OFDLCK locks, the owner is the filp, not the files_struct.
* Because the owner is not even nominally tied to a thread of
* execution, the deadlock detection below can't reasonably work well. Just
* skip it for those.
*
- * In principle, we could do a more limited deadlock detection on FL_FILE_PVT
+ * In principle, we could do a more limited deadlock detection on FL_OFDLCK
* locks that just checks for the case where two tasks are attempting to
* upgrade from read to write locks on the same inode.
*/
@@ -791,9 +779,9 @@ static int posix_locks_deadlock(struct file_lock *caller_fl,
/*
* This deadlock detector can't reasonably detect deadlocks with
- * FL_FILE_PVT locks, since they aren't owned by a process, per-se.
+ * FL_OFDLCK locks, since they aren't owned by a process, per-se.
*/
- if (IS_FILE_PVT(caller_fl))
+ if (IS_OFDLCK(caller_fl))
return 0;
while ((block_fl = what_owner_is_waiting_for(block_fl))) {
@@ -1391,11 +1379,10 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
restart:
break_time = flock->fl_break_time;
- if (break_time != 0) {
+ if (break_time != 0)
break_time -= jiffies;
- if (break_time == 0)
- break_time++;
- }
+ if (break_time == 0)
+ break_time++;
locks_insert_block(flock, new_fl);
spin_unlock(&inode->i_lock);
error = wait_event_interruptible_timeout(new_fl->fl_wait,
@@ -1891,7 +1878,7 @@ EXPORT_SYMBOL_GPL(vfs_test_lock);
static int posix_lock_to_flock(struct flock *flock, struct file_lock *fl)
{
- flock->l_pid = IS_FILE_PVT(fl) ? -1 : fl->fl_pid;
+ flock->l_pid = IS_OFDLCK(fl) ? -1 : fl->fl_pid;
#if BITS_PER_LONG == 32
/*
* Make sure we can represent the posix lock via
@@ -1913,7 +1900,7 @@ static int posix_lock_to_flock(struct flock *flock, struct file_lock *fl)
#if BITS_PER_LONG == 32
static void posix_lock_to_flock64(struct flock64 *flock, struct file_lock *fl)
{
- flock->l_pid = IS_FILE_PVT(fl) ? -1 : fl->fl_pid;
+ flock->l_pid = IS_OFDLCK(fl) ? -1 : fl->fl_pid;
flock->l_start = fl->fl_start;
flock->l_len = fl->fl_end == OFFSET_MAX ? 0 :
fl->fl_end - fl->fl_start + 1;
@@ -1942,13 +1929,13 @@ int fcntl_getlk(struct file *filp, unsigned int cmd, struct flock __user *l)
if (error)
goto out;
- if (cmd == F_GETLKP) {
+ if (cmd == F_OFD_GETLK) {
error = -EINVAL;
if (flock.l_pid != 0)
goto out;
cmd = F_GETLK;
- file_lock.fl_flags |= FL_FILE_PVT;
+ file_lock.fl_flags |= FL_OFDLCK;
file_lock.fl_owner = (fl_owner_t)filp;
}
@@ -2035,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().
*/
@@ -2072,27 +2075,31 @@ 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_FILE_PVT flag and override the owner.
+ * FL_OFDLCK flag and override the owner.
*/
switch (cmd) {
- case F_SETLKP:
+ case F_OFD_SETLK:
error = -EINVAL;
if (flock.l_pid != 0)
goto out;
cmd = F_SETLK;
- file_lock->fl_flags |= FL_FILE_PVT;
+ file_lock->fl_flags |= FL_OFDLCK;
file_lock->fl_owner = (fl_owner_t)filp;
break;
- case F_SETLKPW:
+ case F_OFD_SETLKW:
error = -EINVAL;
if (flock.l_pid != 0)
goto out;
cmd = F_SETLKW;
- file_lock->fl_flags |= FL_FILE_PVT;
+ file_lock->fl_flags |= FL_OFDLCK;
file_lock->fl_owner = (fl_owner_t)filp;
/* Fallthrough */
case F_SETLKW:
@@ -2144,13 +2151,13 @@ int fcntl_getlk64(struct file *filp, unsigned int cmd, struct flock64 __user *l)
if (error)
goto out;
- if (cmd == F_GETLKP) {
+ if (cmd == F_OFD_GETLK) {
error = -EINVAL;
if (flock.l_pid != 0)
goto out;
cmd = F_GETLK64;
- file_lock.fl_flags |= FL_FILE_PVT;
+ file_lock.fl_flags |= FL_OFDLCK;
file_lock.fl_owner = (fl_owner_t)filp;
}
@@ -2207,27 +2214,31 @@ 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_FILE_PVT flag and override the owner.
+ * FL_OFDLCK flag and override the owner.
*/
switch (cmd) {
- case F_SETLKP:
+ case F_OFD_SETLK:
error = -EINVAL;
if (flock.l_pid != 0)
goto out;
cmd = F_SETLK64;
- file_lock->fl_flags |= FL_FILE_PVT;
+ file_lock->fl_flags |= FL_OFDLCK;
file_lock->fl_owner = (fl_owner_t)filp;
break;
- case F_SETLKPW:
+ case F_OFD_SETLKW:
error = -EINVAL;
if (flock.l_pid != 0)
goto out;
cmd = F_SETLKW64;
- file_lock->fl_flags |= FL_FILE_PVT;
+ file_lock->fl_flags |= FL_OFDLCK;
file_lock->fl_owner = (fl_owner_t)filp;
/* Fallthrough */
case F_SETLKW64:
@@ -2413,8 +2424,8 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl,
if (IS_POSIX(fl)) {
if (fl->fl_flags & FL_ACCESS)
seq_printf(f, "ACCESS");
- else if (IS_FILE_PVT(fl))
- seq_printf(f, "FLPVT ");
+ else if (IS_OFDLCK(fl))
+ seq_printf(f, "OFDLCK");
else
seq_printf(f, "POSIX ");
diff --git a/fs/namei.c b/fs/namei.c
index c6157c894fce..80168273396b 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -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;
}
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index 6f3f392d48af..f66c66b9f182 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -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);
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 39c8ef875f91..2c73cae9899d 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -654,9 +654,11 @@ static struct rpc_clnt *create_backchannel_client(struct rpc_create_args *args)
static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses)
{
+ int maxtime = max_cb_time(clp->net);
struct rpc_timeout timeparms = {
- .to_initval = max_cb_time(clp->net),
+ .to_initval = maxtime,
.to_retries = 0,
+ .to_maxval = maxtime,
};
struct rpc_create_args args = {
.net = clp->net,
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 3ba65979a3cd..9a77a5a21557 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -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;
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 2723c1badd01..18881f34737a 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -3627,14 +3627,6 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
/* nfsd4_check_resp_size guarantees enough room for error status */
if (!op->status)
op->status = nfsd4_check_resp_size(resp, 0);
- if (op->status == nfserr_resource && nfsd4_has_session(&resp->cstate)) {
- struct nfsd4_slot *slot = resp->cstate.slot;
-
- if (slot->sl_flags & NFSD4_SLOT_CACHETHIS)
- op->status = nfserr_rep_too_big_to_cache;
- else
- op->status = nfserr_rep_too_big;
- }
if (so) {
so->so_replay.rp_status = op->status;
so->so_replay.rp_buflen = (char *)resp->p - (char *)(statp+1);
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 4e565c814309..732648b270dc 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -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);
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
index af3f7aa73e13..ee1f88419cb0 100644
--- a/fs/ocfs2/dlm/dlmmaster.c
+++ b/fs/ocfs2/dlm/dlmmaster.c
@@ -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)
diff --git a/fs/open.c b/fs/open.c
index 3d30eb1fc95e..9d64679cec73 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -254,17 +254,22 @@ int do_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
return -EBADF;
/*
- * It's not possible to punch hole or perform collapse range
- * on append only file
+ * We can only allow pure fallocate on append only files
*/
- if (mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_COLLAPSE_RANGE)
- && IS_APPEND(inode))
+ if ((mode & ~FALLOC_FL_KEEP_SIZE) && IS_APPEND(inode))
return -EPERM;
if (IS_IMMUTABLE(inode))
return -EPERM;
/*
+ * We can not allow to do any fallocate operation on an active
+ * swapfile
+ */
+ if (IS_SWAPFILE(inode))
+ ret = -ETXTBSY;
+
+ /*
* Revalidate the write permissions, in case security policy has
* changed since the files were opened.
*/
@@ -286,14 +291,6 @@ int do_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
if (((offset + len) > inode->i_sb->s_maxbytes) || ((offset + len) < 0))
return -EFBIG;
- /*
- * There is no need to overlap collapse range with EOF, in which case
- * it is effectively a truncate operation
- */
- if ((mode & FALLOC_FL_COLLAPSE_RANGE) &&
- (offset + len >= i_size_read(inode)))
- return -EINVAL;
-
if (!file->f_op->fallocate)
return -EOPNOTSUPP;
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index 9e363e41dacc..0855f772cd41 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -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:
diff --git a/fs/splice.c b/fs/splice.c
index 9bc07d2b53cf..e246954ea48c 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -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);
diff --git a/fs/super.c b/fs/super.c
index e9dc3c3fe159..48377f7463c0 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -800,7 +800,10 @@ void emergency_remount(void)
static DEFINE_IDA(unnamed_dev_ida);
static DEFINE_SPINLOCK(unnamed_dev_lock);/* protects the above */
-static int unnamed_dev_start = 0; /* don't bother trying below it */
+/* Many userspace utilities consider an FSID of 0 invalid.
+ * Always return at least 1 from get_anon_bdev.
+ */
+static int unnamed_dev_start = 1;
int get_anon_bdev(dev_t *p)
{
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 1b8b91b67fdb..e9ef59b3abb1 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -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
@@ -453,95 +454,3 @@ void sysfs_remove_bin_file(struct kobject *kobj,
kernfs_remove_by_name(kobj->sd, attr->attr.name);
}
EXPORT_SYMBOL_GPL(sysfs_remove_bin_file);
-
-struct sysfs_schedule_callback_struct {
- struct list_head workq_list;
- struct kobject *kobj;
- void (*func)(void *);
- void *data;
- struct module *owner;
- struct work_struct work;
-};
-
-static struct workqueue_struct *sysfs_workqueue;
-static DEFINE_MUTEX(sysfs_workq_mutex);
-static LIST_HEAD(sysfs_workq);
-static void sysfs_schedule_callback_work(struct work_struct *work)
-{
- struct sysfs_schedule_callback_struct *ss = container_of(work,
- struct sysfs_schedule_callback_struct, work);
-
- (ss->func)(ss->data);
- kobject_put(ss->kobj);
- module_put(ss->owner);
- mutex_lock(&sysfs_workq_mutex);
- list_del(&ss->workq_list);
- mutex_unlock(&sysfs_workq_mutex);
- kfree(ss);
-}
-
-/**
- * sysfs_schedule_callback - helper to schedule a callback for a kobject
- * @kobj: object we're acting for.
- * @func: callback function to invoke later.
- * @data: argument to pass to @func.
- * @owner: module owning the callback code
- *
- * sysfs attribute methods must not unregister themselves or their parent
- * kobject (which would amount to the same thing). Attempts to do so will
- * deadlock, since unregistration is mutually exclusive with driver
- * callbacks.
- *
- * Instead methods can call this routine, which will attempt to allocate
- * and schedule a workqueue request to call back @func with @data as its
- * argument in the workqueue's process context. @kobj will be pinned
- * until @func returns.
- *
- * Returns 0 if the request was submitted, -ENOMEM if storage could not
- * be allocated, -ENODEV if a reference to @owner isn't available,
- * -EAGAIN if a callback has already been scheduled for @kobj.
- */
-int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *),
- void *data, struct module *owner)
-{
- struct sysfs_schedule_callback_struct *ss, *tmp;
-
- if (!try_module_get(owner))
- return -ENODEV;
-
- mutex_lock(&sysfs_workq_mutex);
- list_for_each_entry_safe(ss, tmp, &sysfs_workq, workq_list)
- if (ss->kobj == kobj) {
- module_put(owner);
- mutex_unlock(&sysfs_workq_mutex);
- return -EAGAIN;
- }
- mutex_unlock(&sysfs_workq_mutex);
-
- if (sysfs_workqueue == NULL) {
- sysfs_workqueue = create_singlethread_workqueue("sysfsd");
- if (sysfs_workqueue == NULL) {
- module_put(owner);
- return -ENOMEM;
- }
- }
-
- ss = kmalloc(sizeof(*ss), GFP_KERNEL);
- if (!ss) {
- module_put(owner);
- return -ENOMEM;
- }
- kobject_get(kobj);
- ss->kobj = kobj;
- ss->func = func;
- ss->data = data;
- ss->owner = owner;
- INIT_WORK(&ss->work, sysfs_schedule_callback_work);
- INIT_LIST_HEAD(&ss->workq_list);
- mutex_lock(&sysfs_workq_mutex);
- list_add_tail(&ss->workq_list, &sysfs_workq);
- mutex_unlock(&sysfs_workq_mutex);
- queue_work(sysfs_workqueue, &ss->work);
- return 0;
-}
-EXPORT_SYMBOL_GPL(sysfs_schedule_callback);
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index a66ad6196f59..8794423f7efb 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -63,7 +63,8 @@ int __init sysfs_init(void)
{
int err;
- sysfs_root = kernfs_create_root(NULL, 0, NULL);
+ sysfs_root = kernfs_create_root(NULL, KERNFS_ROOT_EXTRA_OPEN_PERM_CHECK,
+ NULL);
if (IS_ERR(sysfs_root))
return PTR_ERR(sysfs_root);
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index a1266089eca1..a81c7b556896 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -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);
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index 75df77d09f75..0479c32c5eb1 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -1344,6 +1344,14 @@ __xfs_get_blocks(
/*
* If this is O_DIRECT or the mpage code calling tell them how large
* the mapping is, so that we can avoid repeated get_blocks calls.
+ *
+ * If the mapping spans EOF, then we have to break the mapping up as the
+ * mapping for blocks beyond EOF must be marked new so that sub block
+ * regions can be correctly zeroed. We can't do this for mappings within
+ * EOF unless the mapping was just allocated or is unwritten, otherwise
+ * the callers would overwrite existing data with zeros. Hence we have
+ * to split the mapping into a range up to and including EOF, and a
+ * second mapping for beyond EOF.
*/
if (direct || size > (1 << inode->i_blkbits)) {
xfs_off_t mapping_size;
@@ -1354,6 +1362,12 @@ __xfs_get_blocks(
ASSERT(mapping_size > 0);
if (mapping_size > size)
mapping_size = size;
+ if (offset < i_size_read(inode) &&
+ offset + mapping_size >= i_size_read(inode)) {
+ /* limit mapping to block that spans EOF */
+ mapping_size = roundup_64(i_size_read(inode) - offset,
+ 1 << inode->i_blkbits);
+ }
if (mapping_size > LONG_MAX)
mapping_size = LONG_MAX;
@@ -1566,6 +1580,16 @@ xfs_vm_write_failed(
xfs_vm_kill_delalloc_range(inode, block_offset,
block_offset + bh->b_size);
+
+ /*
+ * This buffer does not contain data anymore. make sure anyone
+ * who finds it knows that for certain.
+ */
+ clear_buffer_delay(bh);
+ clear_buffer_uptodate(bh);
+ clear_buffer_mapped(bh);
+ clear_buffer_new(bh);
+ clear_buffer_dirty(bh);
}
}
@@ -1599,12 +1623,21 @@ xfs_vm_write_begin(
status = __block_write_begin(page, pos, len, xfs_get_blocks);
if (unlikely(status)) {
struct inode *inode = mapping->host;
+ size_t isize = i_size_read(inode);
xfs_vm_write_failed(inode, page, pos, len);
unlock_page(page);
- if (pos + len > i_size_read(inode))
- truncate_pagecache(inode, i_size_read(inode));
+ /*
+ * If the write is beyond EOF, we only want to kill blocks
+ * allocated in this write, not blocks that were previously
+ * written successfully.
+ */
+ if (pos + len > isize) {
+ ssize_t start = max_t(ssize_t, pos, isize);
+
+ truncate_pagecache_range(inode, start, pos + len);
+ }
page_cache_release(page);
page = NULL;
@@ -1615,9 +1648,12 @@ xfs_vm_write_begin(
}
/*
- * On failure, we only need to kill delalloc blocks beyond EOF because they
- * will never be written. For blocks within EOF, generic_write_end() zeros them
- * so they are safe to leave alone and be written with all the other valid data.
+ * On failure, we only need to kill delalloc blocks beyond EOF in the range of
+ * this specific write because they will never be written. Previous writes
+ * beyond EOF where block allocation succeeded do not need to be trashed, so
+ * only new blocks from this write should be trashed. For blocks within
+ * EOF, generic_write_end() zeros them so they are safe to leave alone and be
+ * written with all the other valid data.
*/
STATIC int
xfs_vm_write_end(
@@ -1640,8 +1676,11 @@ xfs_vm_write_end(
loff_t to = pos + len;
if (to > isize) {
- truncate_pagecache(inode, isize);
+ /* only kill blocks in this write beyond EOF */
+ if (pos > isize)
+ isize = pos;
xfs_vm_kill_delalloc_range(inode, isize, to);
+ truncate_pagecache_range(inode, isize, to);
}
}
return ret;
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index 01b6a0102fbd..abda1124a70f 100644
--- a/fs/xfs/xfs_attr.c
+++ b/fs/xfs/xfs_attr.c
@@ -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)
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c
index fe9587fab17a..511c283459b1 100644
--- a/fs/xfs/xfs_attr_leaf.c
+++ b/fs/xfs/xfs_attr_leaf.c
@@ -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)));
}
diff --git a/fs/xfs/xfs_attr_list.c b/fs/xfs/xfs_attr_list.c
index 01db96f60cf0..833fe5d98d80 100644
--- a/fs/xfs/xfs_attr_list.c
+++ b/fs/xfs/xfs_attr_list.c
@@ -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(
diff --git a/fs/xfs/xfs_attr_remote.c b/fs/xfs/xfs_attr_remote.c
index 6e37823e2932..d2e6e948cec7 100644
--- a/fs/xfs/xfs_attr_remote.c
+++ b/fs/xfs/xfs_attr_remote.c
@@ -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;
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 5b6092ef51ef..f0efc7e970ef 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -5413,6 +5413,7 @@ xfs_bmap_shift_extents(
int whichfork = XFS_DATA_FORK;
int logflags;
xfs_filblks_t blockcount = 0;
+ int total_extents;
if (unlikely(XFS_TEST_ERROR(
(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
@@ -5429,7 +5430,6 @@ xfs_bmap_shift_extents(
ASSERT(current_ext != NULL);
ifp = XFS_IFORK_PTR(ip, whichfork);
-
if (!(ifp->if_flags & XFS_IFEXTENTS)) {
/* Read in all the extents */
error = xfs_iread_extents(tp, ip, whichfork);
@@ -5456,7 +5456,6 @@ xfs_bmap_shift_extents(
/* We are going to change core inode */
logflags = XFS_ILOG_CORE;
-
if (ifp->if_flags & XFS_IFBROOT) {
cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
cur->bc_private.b.firstblock = *firstblock;
@@ -5467,8 +5466,14 @@ xfs_bmap_shift_extents(
logflags |= XFS_ILOG_DEXT;
}
- while (nexts++ < num_exts &&
- *current_ext < XFS_IFORK_NEXTENTS(ip, whichfork)) {
+ /*
+ * There may be delalloc extents in the data fork before the range we
+ * are collapsing out, so we cannot
+ * use the count of real extents here. Instead we have to calculate it
+ * from the incore fork.
+ */
+ total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t);
+ while (nexts++ < num_exts && *current_ext < total_extents) {
gotp = xfs_iext_get_ext(ifp, *current_ext);
xfs_bmbt_get_all(gotp, &got);
@@ -5556,10 +5561,11 @@ xfs_bmap_shift_extents(
}
(*current_ext)++;
+ total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t);
}
/* Check if we are done */
- if (*current_ext == XFS_IFORK_NEXTENTS(ip, whichfork))
+ if (*current_ext == total_extents)
*done = 1;
del_cursor:
@@ -5568,6 +5574,5 @@ del_cursor:
error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
xfs_trans_log_inode(tp, ip, logflags);
-
return error;
}
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index 01f6a646caa1..296160b8e78c 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -1418,6 +1418,8 @@ xfs_zero_file_space(
xfs_off_t end_boundary;
int error;
+ trace_xfs_zero_file_space(ip);
+
granularity = max_t(uint, 1 << mp->m_sb.sb_blocklog, PAGE_CACHE_SIZE);
/*
@@ -1432,9 +1434,18 @@ xfs_zero_file_space(
ASSERT(end_boundary <= offset + len);
if (start_boundary < end_boundary - 1) {
- /* punch out the page cache over the conversion range */
+ /*
+ * punch out delayed allocation blocks and the page cache over
+ * the conversion range
+ */
+ xfs_ilock(ip, XFS_ILOCK_EXCL);
+ error = xfs_bmap_punch_delalloc_range(ip,
+ XFS_B_TO_FSBT(mp, start_boundary),
+ XFS_B_TO_FSB(mp, end_boundary - start_boundary));
+ xfs_iunlock(ip, XFS_ILOCK_EXCL);
truncate_pagecache_range(VFS_I(ip), start_boundary,
end_boundary - 1);
+
/* convert the blocks */
error = xfs_alloc_file_space(ip, start_boundary,
end_boundary - start_boundary - 1,
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
index 107f2fdfe41f..cb10a0aaab3a 100644
--- a/fs/xfs/xfs_buf.c
+++ b/fs/xfs/xfs_buf.c
@@ -1372,21 +1372,29 @@ xfs_buf_iorequest(
xfs_buf_wait_unpin(bp);
xfs_buf_hold(bp);
- /* Set the count to 1 initially, this will stop an I/O
+ /*
+ * Set the count to 1 initially, this will stop an I/O
* completion callout which happens before we have started
* all the I/O from calling xfs_buf_ioend too early.
*/
atomic_set(&bp->b_io_remaining, 1);
_xfs_buf_ioapply(bp);
- _xfs_buf_ioend(bp, 1);
+ /*
+ * If _xfs_buf_ioapply failed, we'll get back here with
+ * only the reference we took above. _xfs_buf_ioend will
+ * drop it to zero, so we'd better not queue it for later,
+ * or we'll free it before it's done.
+ */
+ _xfs_buf_ioend(bp, bp->b_error ? 0 : 1);
xfs_buf_rele(bp);
}
/*
* Waits for I/O to complete on the buffer supplied. It returns immediately if
- * no I/O is pending or there is already a pending error on the buffer. It
- * returns the I/O error code, if any, or 0 if there was no error.
+ * no I/O is pending or there is already a pending error on the buffer, in which
+ * case nothing will ever complete. It returns the I/O error code, if any, or
+ * 0 if there was no error.
*/
int
xfs_buf_iowait(
diff --git a/fs/xfs/xfs_da_btree.h b/fs/xfs/xfs_da_btree.h
index 6e95ea79f5d7..201c6091d26a 100644
--- a/fs/xfs/xfs_da_btree.h
+++ b/fs/xfs/xfs_da_btree.h
@@ -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;
diff --git a/fs/xfs/xfs_export.c b/fs/xfs/xfs_export.c
index 1399e187d425..753e467aa1a5 100644
--- a/fs/xfs/xfs_export.c
+++ b/fs/xfs/xfs_export.c
@@ -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 = {
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 79e96ce98733..830c1c937b88 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -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) {
@@ -679,7 +679,7 @@ xfs_file_dio_aio_write(
goto out;
if (mapping->nrpages) {
- ret = -filemap_write_and_wait_range(VFS_I(ip)->i_mapping,
+ ret = filemap_write_and_wait_range(VFS_I(ip)->i_mapping,
pos, -1);
if (ret)
goto out;
@@ -837,11 +837,19 @@ 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;
+ }
+
+ /*
+ * There is no need to overlap collapse range with EOF,
+ * in which case it is effectively a truncate operation
+ */
+ if (offset + len >= i_size_read(inode)) {
+ error = EINVAL;
goto out_unlock;
}
- ASSERT(offset + len < i_size_read(inode));
new_size = i_size_read(inode) - len;
error = xfs_collapse_file_space(ip, offset, len);
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 5e7a38fa6ee6..768087bedbac 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1334,7 +1334,8 @@ int
xfs_create_tmpfile(
struct xfs_inode *dp,
struct dentry *dentry,
- umode_t mode)
+ umode_t mode,
+ struct xfs_inode **ipp)
{
struct xfs_mount *mp = dp->i_mount;
struct xfs_inode *ip = NULL;
@@ -1402,7 +1403,6 @@ xfs_create_tmpfile(
xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp);
ip->i_d.di_nlink--;
- d_tmpfile(dentry, VFS_I(ip));
error = xfs_iunlink(tp, ip);
if (error)
goto out_trans_abort;
@@ -1415,6 +1415,7 @@ xfs_create_tmpfile(
xfs_qm_dqrele(gdqp);
xfs_qm_dqrele(pdqp);
+ *ipp = ip;
return 0;
out_trans_abort:
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 396cc1fafd0d..f2fcde52b66d 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -334,7 +334,7 @@ int xfs_lookup(struct xfs_inode *dp, struct xfs_name *name,
int xfs_create(struct xfs_inode *dp, struct xfs_name *name,
umode_t mode, xfs_dev_t rdev, struct xfs_inode **ipp);
int xfs_create_tmpfile(struct xfs_inode *dp, struct dentry *dentry,
- umode_t mode);
+ umode_t mode, struct xfs_inode **ipp);
int xfs_remove(struct xfs_inode *dp, struct xfs_name *name,
struct xfs_inode *ip);
int xfs_link(struct xfs_inode *tdp, struct xfs_inode *sip,
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 89b07e43ca28..36d630319a27 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -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,11 +197,23 @@ 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,
struct dentry *dentry,
@@ -353,6 +373,7 @@ xfs_vn_symlink(
out_cleanup_inode:
xfs_cleanup_inode(dir, inode, dentry);
+ iput(inode);
out:
return -error;
}
@@ -1053,11 +1074,7 @@ xfs_vn_tmpfile(
struct dentry *dentry,
umode_t mode)
{
- int error;
-
- error = xfs_create_tmpfile(XFS_I(dir), dentry, mode);
-
- return -error;
+ return xfs_generic_create(dir, dentry, mode, 0, true);
}
static const struct inode_operations xfs_inode_operations = {
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 8497a00e399d..a5f8bd9899d3 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -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);
}
@@ -1181,11 +1183,14 @@ xlog_iodone(xfs_buf_t *bp)
/* log I/O is always issued ASYNC */
ASSERT(XFS_BUF_ISASYNC(bp));
xlog_state_done_syncing(iclog, aborted);
+
/*
- * do not reference the buffer (bp) here as we could race
- * with it being freed after writing the unmount record to the
- * log.
+ * drop the buffer lock now that we are done. Nothing references
+ * the buffer after this, so an unmount waiting on this lock can now
+ * tear it down safely. As such, it is unsafe to reference the buffer
+ * (bp) after the unlock as we could race with it being freed.
*/
+ xfs_buf_unlock(bp);
}
/*
@@ -1368,8 +1373,16 @@ xlog_alloc_log(
bp = xfs_buf_alloc(mp->m_logdev_targp, 0, BTOBB(log->l_iclog_size), 0);
if (!bp)
goto out_free_log;
- bp->b_iodone = xlog_iodone;
+
+ /*
+ * The iclogbuf buffer locks are held over IO but we are not going to do
+ * IO yet. Hence unlock the buffer so that the log IO path can grab it
+ * when appropriately.
+ */
ASSERT(xfs_buf_islocked(bp));
+ xfs_buf_unlock(bp);
+
+ bp->b_iodone = xlog_iodone;
log->l_xbuf = bp;
spin_lock_init(&log->l_icloglock);
@@ -1398,6 +1411,9 @@ xlog_alloc_log(
if (!bp)
goto out_free_iclog;
+ ASSERT(xfs_buf_islocked(bp));
+ xfs_buf_unlock(bp);
+
bp->b_iodone = xlog_iodone;
iclog->ic_bp = bp;
iclog->ic_data = bp->b_addr;
@@ -1422,7 +1438,6 @@ xlog_alloc_log(
iclog->ic_callback_tail = &(iclog->ic_callback);
iclog->ic_datap = (char *)iclog->ic_data + log->l_iclog_hsize;
- ASSERT(xfs_buf_islocked(iclog->ic_bp));
init_waitqueue_head(&iclog->ic_force_wait);
init_waitqueue_head(&iclog->ic_write_wait);
@@ -1631,6 +1646,12 @@ xlog_cksum(
* we transition the iclogs to IOERROR state *after* flushing all existing
* iclogs to disk. This is because we don't want anymore new transactions to be
* started or completed afterwards.
+ *
+ * We lock the iclogbufs here so that we can serialise against IO completion
+ * during unmount. We might be processing a shutdown triggered during unmount,
+ * and that can occur asynchronously to the unmount thread, and hence we need to
+ * ensure that completes before tearing down the iclogbufs. Hence we need to
+ * hold the buffer lock across the log IO to acheive that.
*/
STATIC int
xlog_bdstrat(
@@ -1638,6 +1659,7 @@ xlog_bdstrat(
{
struct xlog_in_core *iclog = bp->b_fspriv;
+ xfs_buf_lock(bp);
if (iclog->ic_state & XLOG_STATE_IOERROR) {
xfs_buf_ioerror(bp, EIO);
xfs_buf_stale(bp);
@@ -1645,7 +1667,8 @@ xlog_bdstrat(
/*
* It would seem logical to return EIO here, but we rely on
* the log state machine to propagate I/O errors instead of
- * doing it here.
+ * doing it here. Similarly, IO completion will unlock the
+ * buffer, so we don't do it here.
*/
return 0;
}
@@ -1847,14 +1870,28 @@ xlog_dealloc_log(
xlog_cil_destroy(log);
/*
- * always need to ensure that the extra buffer does not point to memory
- * owned by another log buffer before we free it.
+ * Cycle all the iclogbuf locks to make sure all log IO completion
+ * is done before we tear down these buffers.
*/
+ iclog = log->l_iclog;
+ for (i = 0; i < log->l_iclog_bufs; i++) {
+ xfs_buf_lock(iclog->ic_bp);
+ xfs_buf_unlock(iclog->ic_bp);
+ iclog = iclog->ic_next;
+ }
+
+ /*
+ * Always need to ensure that the extra buffer does not point to memory
+ * owned by another log buffer before we free it. Also, cycle the lock
+ * first to ensure we've completed IO on it.
+ */
+ xfs_buf_lock(log->l_xbuf);
+ xfs_buf_unlock(log->l_xbuf);
xfs_buf_set_empty(log->l_xbuf, BTOBB(log->l_iclog_size));
xfs_buf_free(log->l_xbuf);
iclog = log->l_iclog;
- for (i=0; i<log->l_iclog_bufs; i++) {
+ for (i = 0; i < log->l_iclog_bufs; i++) {
xfs_buf_free(iclog->ic_bp);
next_iclog = iclog->ic_next;
kmem_free(iclog);
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 993cb19e7d39..944f3d9456a8 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -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);
}
/*
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index 348e4d2ed6e6..dc977b6e6a36 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -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;
}
diff --git a/fs/xfs/xfs_sb.c b/fs/xfs/xfs_sb.c
index 0c0e41bbe4e3..8baf61afae1d 100644
--- a/fs/xfs/xfs_sb.c
+++ b/fs/xfs/xfs_sb.c
@@ -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,
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 205376776377..3494eff8e4eb 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -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;
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index a4ae41c179a8..65d8c793a25c 100644
--- a/fs/xfs/xfs_trace.h
+++ b/fs/xfs/xfs_trace.h
@@ -603,6 +603,7 @@ DEFINE_INODE_EVENT(xfs_readlink);
DEFINE_INODE_EVENT(xfs_inactive_symlink);
DEFINE_INODE_EVENT(xfs_alloc_file_space);
DEFINE_INODE_EVENT(xfs_free_file_space);
+DEFINE_INODE_EVENT(xfs_zero_file_space);
DEFINE_INODE_EVENT(xfs_collapse_file_space);
DEFINE_INODE_EVENT(xfs_readdir);
#ifdef CONFIG_XFS_POSIX_ACL
diff --git a/include/asm-generic/fixmap.h b/include/asm-generic/fixmap.h
index 5a64ca4621f3..f23174fb9ec4 100644
--- a/include/asm-generic/fixmap.h
+++ b/include/asm-generic/fixmap.h
@@ -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 */
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index 1ec08c198b66..a8015a7a55bb 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -693,24 +693,35 @@ static inline int pmd_numa(pmd_t pmd)
#ifndef pte_mknonnuma
static inline pte_t pte_mknonnuma(pte_t pte)
{
- pte = pte_clear_flags(pte, _PAGE_NUMA);
- return pte_set_flags(pte, _PAGE_PRESENT|_PAGE_ACCESSED);
+ pteval_t val = pte_val(pte);
+
+ val &= ~_PAGE_NUMA;
+ val |= (_PAGE_PRESENT|_PAGE_ACCESSED);
+ return __pte(val);
}
#endif
#ifndef pmd_mknonnuma
static inline pmd_t pmd_mknonnuma(pmd_t pmd)
{
- pmd = pmd_clear_flags(pmd, _PAGE_NUMA);
- return pmd_set_flags(pmd, _PAGE_PRESENT|_PAGE_ACCESSED);
+ pmdval_t val = pmd_val(pmd);
+
+ val &= ~_PAGE_NUMA;
+ val |= (_PAGE_PRESENT|_PAGE_ACCESSED);
+
+ return __pmd(val);
}
#endif
#ifndef pte_mknuma
static inline pte_t pte_mknuma(pte_t pte)
{
- pte = pte_set_flags(pte, _PAGE_NUMA);
- return pte_clear_flags(pte, _PAGE_PRESENT);
+ pteval_t val = pte_val(pte);
+
+ val &= ~_PAGE_PRESENT;
+ val |= _PAGE_NUMA;
+
+ return __pte(val);
}
#endif
@@ -729,8 +740,12 @@ static inline void ptep_set_numa(struct mm_struct *mm, unsigned long addr,
#ifndef pmd_mknuma
static inline pmd_t pmd_mknuma(pmd_t pmd)
{
- pmd = pmd_set_flags(pmd, _PAGE_NUMA);
- return pmd_clear_flags(pmd, _PAGE_PRESENT);
+ pmdval_t val = pmd_val(pmd);
+
+ val &= ~_PAGE_PRESENT;
+ val |= _PAGE_NUMA;
+
+ return __pmd(val);
}
#endif
diff --git a/include/asm-generic/resource.h b/include/asm-generic/resource.h
index b4ea8f50fc65..5e752b959054 100644
--- a/include/asm-generic/resource.h
+++ b/include/asm-generic/resource.h
@@ -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 }, \
diff --git a/include/asm-generic/word-at-a-time.h b/include/asm-generic/word-at-a-time.h
index d3909effd725..94f9ea8abcae 100644
--- a/include/asm-generic/word-at-a-time.h
+++ b/include/asm-generic/word-at-a-time.h
@@ -50,11 +50,7 @@ static inline bool has_zero(unsigned long val, unsigned long *data, const struct
}
#ifndef zero_bytemask
-#ifdef CONFIG_64BIT
-#define zero_bytemask(mask) (~0ul << fls64(mask))
-#else
-#define zero_bytemask(mask) (~0ul << fls(mask))
-#endif /* CONFIG_64BIT */
-#endif /* zero_bytemask */
+#define zero_bytemask(mask) (~1ul << __fls(mask))
+#endif
#endif /* _ASM_WORD_AT_A_TIME_H */
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
index 0bb34ca2ad2b..36a5febac2a6 100644
--- a/include/drm/drm_crtc_helper.h
+++ b/include/drm/drm_crtc_helper.h
@@ -125,7 +125,6 @@ struct drm_connector_helper_funcs {
struct drm_encoder *(*best_encoder)(struct drm_connector *connector);
};
-extern int drm_helper_probe_single_connector_modes(struct drm_connector *connector, uint32_t maxX, uint32_t maxY);
extern void drm_helper_disable_unused_functions(struct drm_device *dev);
extern int drm_crtc_helper_set_config(struct drm_mode_set *set);
extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
@@ -161,6 +160,11 @@ static inline void drm_connector_helper_add(struct drm_connector *connector,
}
extern void drm_helper_resume_force_mode(struct drm_device *dev);
+
+/* drm_probe_helper.c */
+extern int drm_helper_probe_single_connector_modes(struct drm_connector
+ *connector, uint32_t maxX,
+ uint32_t maxY);
extern void drm_kms_helper_poll_init(struct drm_device *dev);
extern void drm_kms_helper_poll_fini(struct drm_device *dev);
extern bool drm_helper_hpd_irq_event(struct drm_device *dev);
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index b4f58914bf7d..cfcacec5b89d 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -456,6 +456,10 @@ struct drm_dp_aux_msg {
* transactions. The drm_dp_aux_register_i2c_bus() function registers an
* I2C adapter that can be passed to drm_probe_ddc(). Upon removal, drivers
* should call drm_dp_aux_unregister_i2c_bus() to remove the I2C adapter.
+ *
+ * Note that the aux helper code assumes that the .transfer() function
+ * only modifies the reply field of the drm_dp_aux_msg structure. The
+ * retry logic and i2c helpers assume this is the case.
*/
struct drm_dp_aux {
const char *name;
diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h
index 49376aec2fbb..6dfd64b3a604 100644
--- a/include/drm/drm_pciids.h
+++ b/include/drm/drm_pciids.h
@@ -637,6 +637,22 @@
{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}, \
diff --git a/include/drm/i915_pciids.h b/include/drm/i915_pciids.h
index 940ece4934ba..012d58fa8ff0 100644
--- a/include/drm/i915_pciids.h
+++ b/include/drm/i915_pciids.h
@@ -191,8 +191,8 @@
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 */ \
diff --git a/include/dt-bindings/clk/at91.h b/include/dt-bindings/clock/at91.h
index 0b4cb999a3f7..0b4cb999a3f7 100644
--- a/include/dt-bindings/clk/at91.h
+++ b/include/dt-bindings/clock/at91.h
diff --git a/include/dt-bindings/clock/tegra124-car.h b/include/dt-bindings/clock/tegra124-car.h
index 8c1603b10665..433528ab5161 100644
--- a/include/dt-bindings/clock/tegra124-car.h
+++ b/include/dt-bindings/clock/tegra124-car.h
@@ -29,7 +29,7 @@
/* 10 (register bit affects spdif_in and spdif_out) */
#define TEGRA124_CLK_I2S1 11
#define TEGRA124_CLK_I2C1 12
-#define TEGRA124_CLK_NDFLASH 13
+/* 13 */
#define TEGRA124_CLK_SDMMC1 14
#define TEGRA124_CLK_SDMMC4 15
/* 16 */
@@ -83,7 +83,7 @@
/* 64 */
#define TEGRA124_CLK_UARTD 65
-#define TEGRA124_CLK_UARTE 66
+/* 66 */
#define TEGRA124_CLK_I2C3 67
#define TEGRA124_CLK_SBC4 68
#define TEGRA124_CLK_SDMMC3 69
@@ -97,7 +97,7 @@
#define TEGRA124_CLK_TRACE 77
#define TEGRA124_CLK_SOC_THERM 78
#define TEGRA124_CLK_DTV 79
-#define TEGRA124_CLK_NDSPEED 80
+/* 80 */
#define TEGRA124_CLK_I2CSLOW 81
#define TEGRA124_CLK_DSIB 82
#define TEGRA124_CLK_TSEC 83
diff --git a/include/linux/amba/bus.h b/include/linux/amba/bus.h
index 63b5eff0a80f..fdd7e1b61f60 100644
--- a/include/linux/amba/bus.h
+++ b/include/linux/amba/bus.h
@@ -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;
diff --git a/include/linux/amba/mmci.h b/include/linux/amba/mmci.h
index 32a89cf5ec45..8c98113069ce 100644
--- a/include/linux/amba/mmci.h
+++ b/include/linux/amba/mmci.h
@@ -6,28 +6,9 @@
#include <linux/mmc/host.h>
-
-/*
- * These defines is places here due to access is needed from machine
- * configuration files. The ST Micro version does not have ROD and
- * reuse the voltage registers for direction settings.
- */
-#define MCI_ST_DATA2DIREN (1 << 2)
-#define MCI_ST_CMDDIREN (1 << 3)
-#define MCI_ST_DATA0DIREN (1 << 4)
-#define MCI_ST_DATA31DIREN (1 << 5)
-#define MCI_ST_FBCLKEN (1 << 7)
-#define MCI_ST_DATA74DIREN (1 << 8)
-
-/* Just some dummy forwarding */
-struct dma_chan;
-
/**
* struct mmci_platform_data - platform configuration for the MMCI
* (also known as PL180) block.
- * @f_max: the maximum operational frequency for this host in this
- * platform configuration. When this is specified it takes precedence
- * over the module parameter for the same frequency.
* @ocr_mask: available voltages on the 4 pins from the block, this
* is ignored if a regulator is used, see the MMC_VDD_* masks in
* mmc/host.h
@@ -42,37 +23,14 @@ struct dma_chan;
* @gpio_wp: read this GPIO pin to see if the card is write protected
* @gpio_cd: read this GPIO pin to detect card insertion
* @cd_invert: true if the gpio_cd pin value is active low
- * @capabilities: the capabilities of the block as implemented in
- * this platform, signify anything MMC_CAP_* from mmc/host.h
- * @capabilities2: more capabilities, MMC_CAP2_* from mmc/host.h
- * @sigdir: a bit field indicating for what bits in the MMC bus the host
- * should enable signal direction indication.
- * @dma_filter: function used to select an appropriate RX and TX
- * DMA channel to be used for DMA, if and only if you're deploying the
- * generic DMA engine
- * @dma_rx_param: parameter passed to the DMA allocation
- * filter in order to select an appropriate RX channel. If
- * there is a bidirectional RX+TX channel, then just specify
- * this and leave dma_tx_param set to NULL
- * @dma_tx_param: parameter passed to the DMA allocation
- * filter in order to select an appropriate TX channel. If this
- * is NULL the driver will attempt to use the RX channel as a
- * bidirectional channel
*/
struct mmci_platform_data {
- unsigned int f_max;
unsigned int ocr_mask;
int (*ios_handler)(struct device *, struct mmc_ios *);
unsigned int (*status)(struct device *);
int gpio_wp;
int gpio_cd;
bool cd_invert;
- unsigned long capabilities;
- unsigned long capabilities2;
- u32 sigdir;
- bool (*dma_filter)(struct dma_chan *chan, void *filter_param);
- void *dma_rx_param;
- void *dma_tx_param;
};
#endif
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index c2515851c1aa..d60904b9e505 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -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)
{
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 3b9bfdb83ba6..3c7ec327ebd2 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -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)
diff --git a/include/linux/device.h b/include/linux/device.h
index 233bbbeb768d..d1d1c055b48e 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -566,12 +566,6 @@ extern int __must_check device_create_bin_file(struct device *dev,
const struct bin_attribute *attr);
extern void device_remove_bin_file(struct device *dev,
const struct bin_attribute *attr);
-extern int device_schedule_callback_owner(struct device *dev,
- void (*func)(struct device *dev), struct module *owner);
-
-/* This is a macro to avoid include problems with THIS_MODULE */
-#define device_schedule_callback(dev, func) \
- device_schedule_callback_owner(dev, func, THIS_MODULE)
/* device resource management */
typedef void (*dr_release_t)(struct device *dev, void *res);
@@ -932,10 +926,7 @@ extern int device_online(struct device *dev);
extern struct device *__root_device_register(const char *name,
struct module *owner);
-/*
- * This is a macro to avoid include problems with THIS_MODULE,
- * just as per what is done for device_schedule_callback() above.
- */
+/* This is a macro to avoid include problems with THIS_MODULE */
#define root_device_register(name) \
__root_device_register(name, THIS_MODULE)
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index 8300fb87b84a..72cb0ddb9678 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -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;
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 262dcbb75ffe..024fd03e5d18 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -220,7 +220,6 @@ enum {
BPF_S_ANC_RXHASH,
BPF_S_ANC_CPU,
BPF_S_ANC_ALU_XOR_X,
- BPF_S_ANC_SECCOMP_LD_W,
BPF_S_ANC_VLAN_TAG,
BPF_S_ANC_VLAN_TAG_PRESENT,
BPF_S_ANC_PAY_OFFSET,
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 7a9c5bca2b76..878031227c57 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -815,7 +815,7 @@ static inline struct file *get_file(struct file *f)
#define FL_SLEEP 128 /* A blocking lock */
#define FL_DOWNGRADE_PENDING 256 /* Lease is being downgraded */
#define FL_UNLOCK_PENDING 512 /* Lease is being broken */
-#define FL_FILE_PVT 1024 /* lock is private to the file */
+#define FL_OFDLCK 1024 /* lock is "owned" by struct file */
/*
* Special return value from posix_lock_file() and vfs_lock_file() for
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 9212b017bc72..ae9504b4b67d 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -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;
diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h
index bed128e8f4b1..05e53ccb708b 100644
--- a/include/linux/gpio/consumer.h
+++ b/include/linux/gpio/consumer.h
@@ -1,6 +1,7 @@
#ifndef __LINUX_GPIO_CONSUMER_H
#define __LINUX_GPIO_CONSUMER_H
+#include <linux/bug.h>
#include <linux/err.h>
#include <linux/kernel.h>
@@ -23,6 +24,12 @@ struct gpio_desc *__must_check gpiod_get(struct device *dev,
struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
const char *con_id,
unsigned int idx);
+struct gpio_desc *__must_check gpiod_get_optional(struct device *dev,
+ const char *con_id);
+struct gpio_desc *__must_check gpiod_get_index_optional(struct device *dev,
+ const char *con_id,
+ unsigned int index);
+
void gpiod_put(struct gpio_desc *desc);
struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,
@@ -30,6 +37,12 @@ struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,
struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
const char *con_id,
unsigned int idx);
+struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev,
+ const char *con_id);
+struct gpio_desc *__must_check
+devm_gpiod_get_index_optional(struct device *dev, const char *con_id,
+ unsigned int index);
+
void devm_gpiod_put(struct device *dev, struct gpio_desc *desc);
int gpiod_get_direction(const struct gpio_desc *desc);
@@ -73,6 +86,20 @@ static inline struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
{
return ERR_PTR(-ENOSYS);
}
+
+static inline struct gpio_desc *__must_check
+gpiod_get_optional(struct device *dev, const char *con_id)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline struct gpio_desc *__must_check
+gpiod_get_index_optional(struct device *dev, const char *con_id,
+ unsigned int index)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
static inline void gpiod_put(struct gpio_desc *desc)
{
might_sleep();
@@ -93,6 +120,20 @@ struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
{
return ERR_PTR(-ENOSYS);
}
+
+static inline struct gpio_desc *__must_check
+devm_gpiod_get_optional(struct device *dev, const char *con_id)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline struct gpio_desc *__must_check
+devm_gpiod_get_index_optional(struct device *dev, const char *con_id,
+ unsigned int index)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
static inline void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
{
might_sleep();
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
index 1827b43966d9..573e4f3243d0 100644
--- a/include/linux/gpio/driver.h
+++ b/include/linux/gpio/driver.h
@@ -51,7 +51,10 @@ struct seq_file;
* format specifier for an unsigned int. It is substituted by the actual
* number of the gpio.
* @can_sleep: flag must be set iff get()/set() methods sleep, as they
- * must while accessing GPIO expander chips over I2C or SPI
+ * must while accessing GPIO expander chips over I2C or SPI. This
+ * implies that if the chip supports IRQs, these IRQs need to be threaded
+ * as the chip access may sleep when e.g. reading out the IRQ status
+ * registers.
* @exported: flags if the gpiochip is exported for use from sysfs. Private.
*
* A gpio_chip can help platforms abstract various sources of GPIOs so
diff --git a/include/linux/hsi/hsi.h b/include/linux/hsi/hsi.h
index 39bfd5b89077..3ec06300d535 100644
--- a/include/linux/hsi/hsi.h
+++ b/include/linux/hsi/hsi.h
@@ -68,17 +68,31 @@ enum {
};
/**
+ * struct hsi_channel - channel resource used by the hsi clients
+ * @id: Channel number
+ * @name: Channel name
+ */
+struct hsi_channel {
+ unsigned int id;
+ const char *name;
+};
+
+/**
* struct hsi_config - Configuration for RX/TX HSI modules
* @mode: Bit transmission mode (STREAM or FRAME)
- * @channels: Number of channels to use [1..16]
+ * @channels: Channel resources used by the client
+ * @num_channels: Number of channel resources
+ * @num_hw_channels: Number of channels the transceiver is configured for [1..16]
* @speed: Max bit transmission speed (Kbit/s)
* @flow: RX flow type (SYNCHRONIZED or PIPELINE)
* @arb_mode: Arbitration mode for TX frame (Round robin, priority)
*/
struct hsi_config {
- unsigned int mode;
- unsigned int channels;
- unsigned int speed;
+ unsigned int mode;
+ struct hsi_channel *channels;
+ unsigned int num_channels;
+ unsigned int num_hw_channels;
+ unsigned int speed;
union {
unsigned int flow; /* RX only */
unsigned int arb_mode; /* TX only */
@@ -282,6 +296,21 @@ struct hsi_controller *hsi_alloc_controller(unsigned int n_ports, gfp_t flags);
void hsi_put_controller(struct hsi_controller *hsi);
int hsi_register_controller(struct hsi_controller *hsi);
void hsi_unregister_controller(struct hsi_controller *hsi);
+struct hsi_client *hsi_new_client(struct hsi_port *port,
+ struct hsi_board_info *info);
+int hsi_remove_client(struct device *dev, void *data);
+void hsi_port_unregister_clients(struct hsi_port *port);
+
+#ifdef CONFIG_OF
+void hsi_add_clients_from_dt(struct hsi_port *port,
+ struct device_node *clients);
+#else
+static inline void hsi_add_clients_from_dt(struct hsi_port *port,
+ struct device_node *clients)
+{
+ return;
+}
+#endif
static inline void hsi_controller_set_drvdata(struct hsi_controller *hsi,
void *data)
@@ -305,6 +334,8 @@ static inline struct hsi_port *hsi_find_port_num(struct hsi_controller *hsi,
*/
int hsi_async(struct hsi_client *cl, struct hsi_msg *msg);
+int hsi_get_channel_id_by_name(struct hsi_client *cl, char *name);
+
/**
* hsi_id - Get HSI controller ID associated to a client
* @cl: Pointer to a HSI client
diff --git a/include/linux/hsi/ssi_protocol.h b/include/linux/hsi/ssi_protocol.h
new file mode 100644
index 000000000000..1433651be0dc
--- /dev/null
+++ b/include/linux/hsi/ssi_protocol.h
@@ -0,0 +1,42 @@
+/*
+ * ssip_slave.h
+ *
+ * SSIP slave support header file
+ *
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Carlos Chinea <carlos.chinea@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef __LINUX_SSIP_SLAVE_H__
+#define __LINUX_SSIP_SLAVE_H__
+
+#include <linux/hsi/hsi.h>
+
+static inline void ssip_slave_put_master(struct hsi_client *master)
+{
+}
+
+struct hsi_client *ssip_slave_get_master(struct hsi_client *slave);
+int ssip_slave_start_tx(struct hsi_client *master);
+int ssip_slave_stop_tx(struct hsi_client *master);
+void ssip_reset_event(struct hsi_client *master);
+
+int ssip_slave_running(struct hsi_client *master);
+
+#endif /* __LINUX_SSIP_SLAVE_H__ */
+
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index 5b337cf8fb86..b65166de1d9d 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -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
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index ab7359fde987..2d7b4f139c32 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -147,15 +147,17 @@ hv_get_ringbuffer_availbytes(struct hv_ring_buffer_info *rbi,
* 0 . 13 (Windows Server 2008)
* 1 . 1 (Windows 7)
* 2 . 4 (Windows 8)
+ * 3 . 0 (Windows 8 R2)
*/
#define VERSION_WS2008 ((0 << 16) | (13))
#define VERSION_WIN7 ((1 << 16) | (1))
#define VERSION_WIN8 ((2 << 16) | (4))
+#define VERSION_WIN8_1 ((3 << 16) | (0))
#define VERSION_INVAL -1
-#define VERSION_CURRENT VERSION_WIN8
+#define VERSION_CURRENT VERSION_WIN8_1
/* Make maximum size of pipe payload of 16K */
#define MAX_PIPE_DATA_PAYLOAD (sizeof(u8) * 16384)
diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h
index 7c8b20b120ea..a9a53b12397b 100644
--- a/include/linux/if_macvlan.h
+++ b/include/linux/if_macvlan.h
@@ -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,
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 13bbbde00e68..b2acc4a1b13c 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -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_) */
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index c7bfac1c4a7b..051c85032f48 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -203,7 +203,40 @@ static inline int check_wakeup_irqs(void) { return 0; }
extern cpumask_var_t irq_default_affinity;
-extern int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask);
+/* Internal implementation. Use the helpers below */
+extern int __irq_set_affinity(unsigned int irq, const struct cpumask *cpumask,
+ bool force);
+
+/**
+ * irq_set_affinity - Set the irq affinity of a given irq
+ * @irq: Interrupt to set affinity
+ * @cpumask: cpumask
+ *
+ * Fails if cpumask does not contain an online CPU
+ */
+static inline int
+irq_set_affinity(unsigned int irq, const struct cpumask *cpumask)
+{
+ return __irq_set_affinity(irq, cpumask, false);
+}
+
+/**
+ * irq_force_affinity - Force the irq affinity of a given irq
+ * @irq: Interrupt to set affinity
+ * @cpumask: cpumask
+ *
+ * Same as irq_set_affinity, but without checking the mask against
+ * online cpus.
+ *
+ * Solely for low level cpu hotplug code, where we need to make per
+ * cpu interrupts affine before the cpu becomes online.
+ */
+static inline int
+irq_force_affinity(unsigned int irq, const struct cpumask *cpumask)
+{
+ return __irq_set_affinity(irq, cpumask, true);
+}
+
extern int irq_can_set_affinity(unsigned int irq);
extern int irq_select_affinity(unsigned int irq);
@@ -239,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;
diff --git a/include/linux/ipmi.h b/include/linux/ipmi.h
index 1f9f56e28851..76d2acbfa7c6 100644
--- a/include/linux/ipmi.h
+++ b/include/linux/ipmi.h
@@ -237,7 +237,7 @@ int ipmi_set_maintenance_mode(ipmi_user_t user, int mode);
* The first user that sets this to TRUE will receive all events that
* have been queued while no one was waiting for events.
*/
-int ipmi_set_gets_events(ipmi_user_t user, int val);
+int ipmi_set_gets_events(ipmi_user_t user, bool val);
/*
* Called when a new SMI is registered. This will also be called on
diff --git a/include/linux/ipmi_smi.h b/include/linux/ipmi_smi.h
index 8ea3fe0b9759..bd349240d50e 100644
--- a/include/linux/ipmi_smi.h
+++ b/include/linux/ipmi_smi.h
@@ -109,12 +109,19 @@ struct ipmi_smi_handlers {
events from the BMC we are attached to. */
void (*request_events)(void *send_info);
+ /* Called by the upper layer when some user requires that the
+ interface watch for events, received messages, watchdog
+ pretimeouts, or not. Used by the SMI to know if it should
+ watch for these. This may be NULL if the SMI does not
+ implement it. */
+ void (*set_need_watch)(void *send_info, bool enable);
+
/* Called when the interface should go into "run to
completion" mode. If this call sets the value to true, the
interface should make sure that all messages are flushed
out and that none are pending, and any new requests are run
to completion immediately. */
- void (*set_run_to_completion)(void *send_info, int run_to_completion);
+ void (*set_run_to_completion)(void *send_info, bool run_to_completion);
/* Called to poll for work to do. This is so upper layers can
poll for operations during things like crash dumps. */
@@ -125,7 +132,7 @@ struct ipmi_smi_handlers {
setting. The message handler does the mode handling. Note
that this is called from interrupt context, so it cannot
block. */
- void (*set_maintenance_mode)(void *send_info, int enable);
+ void (*set_maintenance_mode)(void *send_info, bool enable);
/* Tell the handler that we are using it/not using it. The
message handler get the modules that this handler belongs
diff --git a/include/linux/irq.h b/include/linux/irq.h
index d278838908cb..5c57efb863d0 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -394,7 +394,8 @@ extern void remove_percpu_irq(unsigned int irq, struct irqaction *act);
extern void irq_cpu_online(void);
extern void irq_cpu_offline(void);
-extern int __irq_set_affinity_locked(struct irq_data *data, const struct cpumask *cpumask);
+extern int irq_set_affinity_locked(struct irq_data *data,
+ const struct cpumask *cpumask, bool force);
#if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_PENDING_IRQ)
void irq_move_irq(struct irq_data *data);
@@ -602,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);
diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h
index b0122dc6f96a..ca1be5c9136c 100644
--- a/include/linux/kernfs.h
+++ b/include/linux/kernfs.h
@@ -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 */
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 1de36be64df4..5ab4e3a76721 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -822,6 +822,7 @@ struct ata_port {
unsigned long qc_allocated;
unsigned int qc_active;
int nr_active_links; /* #links with active qcs */
+ unsigned int last_tag; /* track next tag hw expects */
struct ata_link link; /* host default link */
struct ata_link *slave_link; /* see ata_slave_link_init() */
diff --git a/include/linux/linkage.h b/include/linux/linkage.h
index 34a513a2727b..a6a42dd02466 100644
--- a/include/linux/linkage.h
+++ b/include/linux/linkage.h
@@ -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
diff --git a/include/linux/mdio-gpio.h b/include/linux/mdio-gpio.h
index 7c9fe3c2be73..66c30a763b10 100644
--- a/include/linux/mdio-gpio.h
+++ b/include/linux/mdio-gpio.h
@@ -17,6 +17,11 @@ struct mdio_gpio_platform_data {
/* GPIO numbers for bus pins */
unsigned int mdc;
unsigned int mdio;
+ unsigned int mdo;
+
+ bool mdc_active_low;
+ bool mdio_active_low;
+ bool mdo_active_low;
unsigned int phy_mask;
int irqs[PHY_MAX_ADDR];
diff --git a/include/linux/mfd/rtsx_common.h b/include/linux/mfd/rtsx_common.h
index 7c36cc55d2c7..443176ee1ab0 100644
--- a/include/linux/mfd/rtsx_common.h
+++ b/include/linux/mfd/rtsx_common.h
@@ -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
diff --git a/include/linux/mfd/rtsx_pci.h b/include/linux/mfd/rtsx_pci.h
index 8d6bbd609ad9..a3835976f7c6 100644
--- a/include/linux/mfd/rtsx_pci.h
+++ b/include/linux/mfd/rtsx_pci.h
@@ -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);
diff --git a/include/linux/mfd/tc3589x.h b/include/linux/mfd/tc3589x.h
index 6b8e1ff4672b..e6088c2e2092 100644
--- a/include/linux/mfd/tc3589x.h
+++ b/include/linux/mfd/tc3589x.h
@@ -111,7 +111,6 @@ enum tx3589x_block {
#define TC3589x_INT_PORIRQ 7
#define TC3589x_NR_INTERNAL_IRQS 8
-#define TC3589x_INT_GPIO(x) (TC3589x_NR_INTERNAL_IRQS + (x))
struct tc3589x {
struct mutex lock;
diff --git a/include/linux/mlx4/qp.h b/include/linux/mlx4/qp.h
index b66e7610d4ee..7040dc98ff8b 100644
--- a/include/linux/mlx4/qp.h
+++ b/include/linux/mlx4/qp.h
@@ -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,
diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h
index 407bdb67fd4f..3406cfb1267a 100644
--- a/include/linux/mlx5/device.h
+++ b/include/linux/mlx5/device.h
@@ -179,6 +179,7 @@ enum {
MLX5_DEV_CAP_FLAG_BAD_QKEY_CNTR = 1LL << 9,
MLX5_DEV_CAP_FLAG_APM = 1LL << 17,
MLX5_DEV_CAP_FLAG_ATOMIC = 1LL << 18,
+ MLX5_DEV_CAP_FLAG_BLOCK_MCAST = 1LL << 23,
MLX5_DEV_CAP_FLAG_ON_DMND_PG = 1LL << 24,
MLX5_DEV_CAP_FLAG_CQ_MODER = 1LL << 29,
MLX5_DEV_CAP_FLAG_RESIZE_CQ = 1LL << 30,
diff --git a/include/linux/mlx5/qp.h b/include/linux/mlx5/qp.h
index f829ad80ff28..9709b30e2d69 100644
--- a/include/linux/mlx5/qp.h
+++ b/include/linux/mlx5/qp.h
@@ -146,6 +146,7 @@ enum {
enum {
MLX5_QP_LAT_SENSITIVE = 1 << 28,
+ MLX5_QP_BLOCK_MCAST = 1 << 30,
MLX5_QP_ENABLE_SIG = 1 << 31,
};
diff --git a/include/linux/mm.h b/include/linux/mm.h
index bf9811e1321a..d6777060449f 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -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
diff --git a/include/linux/mtd/spear_smi.h b/include/linux/mtd/spear_smi.h
index 8ae1726044c3..581603ac1277 100644
--- a/include/linux/mtd/spear_smi.h
+++ b/include/linux/mtd/spear_smi.h
@@ -1,6 +1,6 @@
/*
* Copyright © 2010 ST Microelectronics
- * Shiraz Hashim <shiraz.hashim@st.com>
+ * Shiraz Hashim <shiraz.linux.kernel@gmail.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
diff --git a/include/linux/net.h b/include/linux/net.h
index 94734a6259a4..17d83393afcc 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -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; \
})
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 7ed3a3aa6604..b42d07b0390b 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -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,10 +3056,19 @@ 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, \
updev = netdev_all_upper_get_next_dev_rcu(dev, &(iter)); \
@@ -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)
{
diff --git a/include/linux/netfilter/nf_conntrack_proto_gre.h b/include/linux/netfilter/nf_conntrack_proto_gre.h
index ec2ffaf418c8..df78dc2b5524 100644
--- a/include/linux/netfilter/nf_conntrack_proto_gre.h
+++ b/include/linux/netfilter/nf_conntrack_proto_gre.h
@@ -87,7 +87,6 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir,
/* delete keymap entries */
void nf_ct_gre_keymap_destroy(struct nf_conn *ct);
-void nf_ct_gre_keymap_flush(struct net *net);
void nf_nat_need_gre(void);
#endif /* __KERNEL__ */
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index aad8eeaf416d..f64b01787ddc 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -169,4 +169,11 @@ struct netlink_tap {
extern int netlink_add_tap(struct netlink_tap *nt);
extern int netlink_remove_tap(struct netlink_tap *nt);
+bool __netlink_ns_capable(const struct netlink_skb_parms *nsp,
+ struct user_namespace *ns, int cap);
+bool netlink_ns_capable(const struct sk_buff *skb,
+ struct user_namespace *ns, int cap);
+bool netlink_capable(const struct sk_buff *skb, int cap);
+bool netlink_net_capable(const struct sk_buff *skb, int cap);
+
#endif /* __LINUX_NETLINK_H */
diff --git a/include/linux/of.h b/include/linux/of.h
index 919bf211877d..e6f0988c1c68 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -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>";
}
@@ -374,6 +374,11 @@ static inline struct device_node *of_find_matching_node_and_match(
return NULL;
}
+static inline struct device_node *of_find_node_by_path(const char *path)
+{
+ return NULL;
+}
+
static inline struct device_node *of_get_parent(const struct device_node *node)
{
return NULL;
diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h
index f14123a5a9df..38fc05036015 100644
--- a/include/linux/of_gpio.h
+++ b/include/linux/of_gpio.h
@@ -19,7 +19,6 @@
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/of.h>
-#include <linux/gpio/consumer.h>
struct device_node;
@@ -48,7 +47,7 @@ static inline struct of_mm_gpio_chip *to_of_mm_gpio_chip(struct gpio_chip *gc)
return container_of(gc, struct of_mm_gpio_chip, gc);
}
-extern struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
+extern int of_get_named_gpio_flags(struct device_node *np,
const char *list_name, int index, enum of_gpio_flags *flags);
extern int of_mm_gpiochip_add(struct device_node *np,
@@ -63,10 +62,10 @@ extern int of_gpio_simple_xlate(struct gpio_chip *gc,
#else /* CONFIG_OF_GPIO */
/* Drivers may not strictly depend on the GPIO support, so let them link. */
-static inline struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
+static inline int of_get_named_gpio_flags(struct device_node *np,
const char *list_name, int index, enum of_gpio_flags *flags)
{
- return ERR_PTR(-ENOSYS);
+ return -ENOSYS;
}
static inline int of_gpio_simple_xlate(struct gpio_chip *gc,
@@ -81,18 +80,6 @@ static inline void of_gpiochip_remove(struct gpio_chip *gc) { }
#endif /* CONFIG_OF_GPIO */
-static inline int of_get_named_gpio_flags(struct device_node *np,
- const char *list_name, int index, enum of_gpio_flags *flags)
-{
- struct gpio_desc *desc;
- desc = of_get_named_gpiod_flags(np, list_name, index, flags);
-
- if (IS_ERR(desc))
- return PTR_ERR(desc);
- else
- return desc_to_gpio(desc);
-}
-
/**
* of_gpio_named_count() - Count GPIOs for a device
* @np: device node to count GPIOs for
@@ -129,22 +116,6 @@ static inline int of_gpio_count(struct device_node *np)
return of_gpio_named_count(np, "gpios");
}
-/**
- * of_get_gpiod_flags() - Get a GPIO descriptor and flags to use with GPIO API
- * @np: device node to get GPIO from
- * @index: index of the GPIO
- * @flags: a flags pointer to fill in
- *
- * Returns GPIO descriptor to use with Linux generic GPIO API, or a errno
- * value on the error condition. If @flags is not NULL the function also fills
- * in flags for the GPIO.
- */
-static inline struct gpio_desc *of_get_gpiod_flags(struct device_node *np,
- int index, enum of_gpio_flags *flags)
-{
- return of_get_named_gpiod_flags(np, "gpios", index, flags);
-}
-
static inline int of_get_gpio_flags(struct device_node *np, int index,
enum of_gpio_flags *flags)
{
diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h
index 3f23b4472c31..6404253d810d 100644
--- a/include/linux/of_irq.h
+++ b/include/linux/of_irq.h
@@ -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)
diff --git a/include/linux/of_mdio.h b/include/linux/of_mdio.h
index 6fe8464ed767..881a7c3571f4 100644
--- a/include/linux/of_mdio.h
+++ b/include/linux/of_mdio.h
@@ -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)
diff --git a/include/linux/omap-dma.h b/include/linux/omap-dma.h
index 41a13e70f41f..7944cdc27bed 100644
--- a/include/linux/omap-dma.h
+++ b/include/linux/omap-dma.h
@@ -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)
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 3356abcfff18..3ef6ea12806a 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -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;
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 24126c4b27b5..4d0221fd0688 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -75,6 +75,7 @@ typedef enum {
PHY_INTERFACE_MODE_SMII,
PHY_INTERFACE_MODE_XGMII,
PHY_INTERFACE_MODE_MOCA,
+ PHY_INTERFACE_MODE_QSGMII,
PHY_INTERFACE_MODE_MAX,
} phy_interface_t;
@@ -116,6 +117,8 @@ static inline const char *phy_modes(phy_interface_t interface)
return "xgmii";
case PHY_INTERFACE_MODE_MOCA:
return "moca";
+ case PHY_INTERFACE_MODE_QSGMII:
+ return "qsgmii";
default:
return "unknown";
}
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
index e2f5ca96cddc..2760744cb2a7 100644
--- a/include/linux/phy/phy.h
+++ b/include/linux/phy/phy.h
@@ -174,21 +174,29 @@ void devm_of_phy_provider_unregister(struct device *dev,
#else
static inline int phy_pm_runtime_get(struct phy *phy)
{
+ if (!phy)
+ return 0;
return -ENOSYS;
}
static inline int phy_pm_runtime_get_sync(struct phy *phy)
{
+ if (!phy)
+ return 0;
return -ENOSYS;
}
static inline int phy_pm_runtime_put(struct phy *phy)
{
+ if (!phy)
+ return 0;
return -ENOSYS;
}
static inline int phy_pm_runtime_put_sync(struct phy *phy)
{
+ if (!phy)
+ return 0;
return -ENOSYS;
}
@@ -204,21 +212,29 @@ static inline void phy_pm_runtime_forbid(struct phy *phy)
static inline int phy_init(struct phy *phy)
{
+ if (!phy)
+ return 0;
return -ENOSYS;
}
static inline int phy_exit(struct phy *phy)
{
+ if (!phy)
+ return 0;
return -ENOSYS;
}
static inline int phy_power_on(struct phy *phy)
{
+ if (!phy)
+ return 0;
return -ENOSYS;
}
static inline int phy_power_off(struct phy *phy)
{
+ if (!phy)
+ return 0;
return -ENOSYS;
}
diff --git a/include/linux/reboot.h b/include/linux/reboot.h
index 9e7db9e73cc1..48bf152761c7 100644
--- a/include/linux/reboot.h
+++ b/include/linux/reboot.h
@@ -20,13 +20,13 @@ enum reboot_mode {
extern enum reboot_mode reboot_mode;
enum reboot_type {
- BOOT_TRIPLE = 't',
- BOOT_KBD = 'k',
- BOOT_BIOS = 'b',
- BOOT_ACPI = 'a',
- BOOT_EFI = 'e',
- BOOT_CF9 = 'p',
- BOOT_CF9_COND = 'q',
+ BOOT_TRIPLE = 't',
+ BOOT_KBD = 'k',
+ BOOT_BIOS = 'b',
+ BOOT_ACPI = 'a',
+ BOOT_EFI = 'e',
+ BOOT_CF9_FORCE = 'p',
+ BOOT_CF9_SAFE = 'q',
};
extern enum reboot_type reboot_type;
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
index e530681bea70..1a4a8c157b31 100644
--- a/include/linux/regulator/consumer.h
+++ b/include/linux/regulator/consumer.h
@@ -258,14 +258,14 @@ regulator_get_exclusive(struct device *dev, const char *id)
static inline struct regulator *__must_check
regulator_get_optional(struct device *dev, const char *id)
{
- return NULL;
+ return ERR_PTR(-ENODEV);
}
static inline struct regulator *__must_check
devm_regulator_get_optional(struct device *dev, const char *id)
{
- return NULL;
+ return ERR_PTR(-ENODEV);
}
static inline void regulator_put(struct regulator *regulator)
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 8e3e66ac0a52..953937ea5233 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -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
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 25f54c79f757..221b2bde3723 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -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
diff --git a/include/linux/serio.h b/include/linux/serio.h
index 36aac733840a..9f779c7a2da4 100644
--- a/include/linux/serio.h
+++ b/include/linux/serio.h
@@ -23,6 +23,7 @@ struct serio {
char name[32];
char phys[32];
+ char firmware_id[128];
bool manual_bind;
diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index f2f7398848cf..d82abd40a3c0 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -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 */
diff --git a/include/linux/sock_diag.h b/include/linux/sock_diag.h
index 54f91d35e5fd..46cca4c06848 100644
--- a/include/linux/sock_diag.h
+++ b/include/linux/sock_diag.h
@@ -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
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 084354b0e814..5ffaa3443712 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -179,9 +179,6 @@ struct sysfs_ops {
#ifdef CONFIG_SYSFS
-int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *),
- void *data, struct module *owner);
-
int __must_check sysfs_create_dir_ns(struct kobject *kobj, const void *ns);
void sysfs_remove_dir(struct kobject *kobj);
int __must_check sysfs_rename_dir_ns(struct kobject *kobj, const char *new_name,
@@ -255,12 +252,6 @@ static inline void sysfs_enable_ns(struct kernfs_node *kn)
#else /* CONFIG_SYSFS */
-static inline int sysfs_schedule_callback(struct kobject *kobj,
- void (*func)(void *), void *data, struct module *owner)
-{
- return -ENOSYS;
-}
-
static inline int sysfs_create_dir_ns(struct kobject *kobj, const void *ns)
{
return 0;
diff --git a/include/linux/wait.h b/include/linux/wait.h
index e7d9d9ed14f5..bd68819f0815 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -191,11 +191,23 @@ wait_queue_head_t *bit_waitqueue(void *, int);
(!__builtin_constant_p(state) || \
state == TASK_INTERRUPTIBLE || state == TASK_KILLABLE) \
+/*
+ * The below macro ___wait_event() has an explicit shadow of the __ret
+ * variable when used from the wait_event_*() macros.
+ *
+ * This is so that both can use the ___wait_cond_timeout() construct
+ * to wrap the condition.
+ *
+ * The type inconsistency of the wait_event_*() __ret variable is also
+ * on purpose; we use long where we can return timeout values and int
+ * otherwise.
+ */
+
#define ___wait_event(wq, condition, state, exclusive, ret, cmd) \
({ \
__label__ __out; \
wait_queue_t __wait; \
- long __ret = ret; \
+ long __ret = ret; /* explicit shadow */ \
\
INIT_LIST_HEAD(&__wait.task_list); \
if (exclusive) \
diff --git a/include/net/af_vsock.h b/include/net/af_vsock.h
index 7d64d3609ec9..428277869400 100644
--- a/include/net/af_vsock.h
+++ b/include/net/af_vsock.h
@@ -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 ****/
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index f3539a15c411..f856e5a746fa 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3669,6 +3669,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
*
* @wiphy: the wiphy reporting the BSS
diff --git a/include/net/dst.h b/include/net/dst.h
index 46ed958e0c6e..71c60f42be48 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -45,7 +45,7 @@ struct dst_entry {
void *__pad1;
#endif
int (*input)(struct sk_buff *);
- int (*output)(struct sk_buff *);
+ int (*output)(struct sock *sk, struct sk_buff *skb);
unsigned short flags;
#define DST_HOST 0x0001
@@ -367,7 +367,11 @@ static inline struct dst_entry *skb_dst_pop(struct sk_buff *skb)
return child;
}
-int dst_discard(struct sk_buff *skb);
+int dst_discard_sk(struct sock *sk, struct sk_buff *skb);
+static inline int dst_discard(struct sk_buff *skb)
+{
+ return dst_discard_sk(skb->sk, skb);
+}
void *dst_alloc(struct dst_ops *ops, struct net_device *dev, int initial_ref,
int initial_obsolete, unsigned short flags);
void __dst_free(struct dst_entry *dst);
@@ -449,9 +453,13 @@ static inline void dst_set_expires(struct dst_entry *dst, int timeout)
}
/* Output packet to network from transport. */
+static inline int dst_output_sk(struct sock *sk, struct sk_buff *skb)
+{
+ return skb_dst(skb)->output(sk, skb);
+}
static inline int dst_output(struct sk_buff *skb)
{
- return skb_dst(skb)->output(skb);
+ return dst_output_sk(skb->sk, skb);
}
/* Input packet from network to transport. */
diff --git a/include/net/flow.h b/include/net/flow.h
index 64fd24836650..8109a159d1b3 100644
--- a/include/net/flow.h
+++ b/include/net/flow.h
@@ -11,6 +11,14 @@
#include <linux/in6.h>
#include <linux/atomic.h>
+/*
+ * ifindex generation is per-net namespace, and loopback is
+ * always the 1st device in ns (see net_dev_init), thus any
+ * loopback device should get ifindex 1
+ */
+
+#define LOOPBACK_IFINDEX 1
+
struct flowi_common {
int flowic_oif;
int flowic_iif;
@@ -80,7 +88,7 @@ static inline void flowi4_init_output(struct flowi4 *fl4, int oif,
__be16 dport, __be16 sport)
{
fl4->flowi4_oif = oif;
- fl4->flowi4_iif = 0;
+ fl4->flowi4_iif = LOOPBACK_IFINDEX;
fl4->flowi4_mark = mark;
fl4->flowi4_tos = tos;
fl4->flowi4_scope = scope;
diff --git a/include/net/inet6_connection_sock.h b/include/net/inet6_connection_sock.h
index f981ba7adeed..74af137304be 100644
--- a/include/net/inet6_connection_sock.h
+++ b/include/net/inet6_connection_sock.h
@@ -40,7 +40,7 @@ void inet6_csk_reqsk_queue_hash_add(struct sock *sk, struct request_sock *req,
void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr);
-int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl);
+int inet6_csk_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl);
struct dst_entry *inet6_csk_update_pmtu(struct sock *sk, u32 mtu);
#endif /* _INET6_CONNECTION_SOCK_H */
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index c55aeed41ace..7a4313887568 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -36,7 +36,7 @@ struct tcp_congestion_ops;
* (i.e. things that depend on the address family)
*/
struct inet_connection_sock_af_ops {
- int (*queue_xmit)(struct sk_buff *skb, struct flowi *fl);
+ int (*queue_xmit)(struct sock *sk, struct sk_buff *skb, struct flowi *fl);
void (*send_check)(struct sock *sk, struct sk_buff *skb);
int (*rebuild_header)(struct sock *sk);
void (*sk_rx_dst_set)(struct sock *sk, const struct sk_buff *skb);
diff --git a/include/net/ip.h b/include/net/ip.h
index 25064c28e059..3ec2b0fb9d83 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -104,14 +104,19 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
struct net_device *orig_dev);
int ip_local_deliver(struct sk_buff *skb);
int ip_mr_input(struct sk_buff *skb);
-int ip_output(struct sk_buff *skb);
-int ip_mc_output(struct sk_buff *skb);
+int ip_output(struct sock *sk, struct sk_buff *skb);
+int ip_mc_output(struct sock *sk, struct sk_buff *skb);
int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
int ip_do_nat(struct sk_buff *skb);
void ip_send_check(struct iphdr *ip);
int __ip_local_out(struct sk_buff *skb);
-int ip_local_out(struct sk_buff *skb);
-int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl);
+int ip_local_out_sk(struct sock *sk, struct sk_buff *skb);
+static inline int ip_local_out(struct sk_buff *skb)
+{
+ return ip_local_out_sk(skb->sk, skb);
+}
+
+int ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl);
void ip_init(void);
int ip_append_data(struct sock *sk, struct flowi4 *fl4,
int getfrag(void *from, char *to, int offset, int len,
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index 3c3bb184eb8f..216cecce65e9 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -32,6 +32,11 @@ struct route_info {
#define RT6_LOOKUP_F_SRCPREF_PUBLIC 0x00000010
#define RT6_LOOKUP_F_SRCPREF_COA 0x00000020
+/* We do not (yet ?) support IPv6 jumbograms (RFC 2675)
+ * Unlike IPv4, hdr->seg_len doesn't include the IPv6 header
+ */
+#define IP6_MAX_MTU (0xFFFF + sizeof(struct ipv6hdr))
+
/*
* rt6_srcprefs2flags() and rt6_flags2srcprefs() translate
* between IPV6_ADDR_PREFERENCES socket option values
@@ -122,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);
/*
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
index e77c10405d51..a4daf9eb8562 100644
--- a/include/net/ip_tunnels.h
+++ b/include/net/ip_tunnels.h
@@ -153,7 +153,7 @@ static inline u8 ip_tunnel_ecn_encap(u8 tos, const struct iphdr *iph,
}
int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto);
-int iptunnel_xmit(struct rtable *rt, struct sk_buff *skb,
+int iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
__be32 src, __be32 dst, __u8 proto,
__u8 tos, __u8 ttl, __be16 df, bool xnet);
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 4f541f11ce63..d640925bc454 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -731,7 +731,7 @@ struct dst_entry *ip6_blackhole_route(struct net *net,
* skb processing functions
*/
-int ip6_output(struct sk_buff *skb);
+int ip6_output(struct sock *sk, struct sk_buff *skb);
int ip6_forward(struct sk_buff *skb);
int ip6_input(struct sk_buff *skb);
int ip6_mc_input(struct sk_buff *skb);
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 79387f73f875..5f9eb260990f 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -9,6 +9,7 @@
#include <linux/list.h>
#include <linux/sysctl.h>
+#include <net/flow.h>
#include <net/netns/core.h>
#include <net/netns/mib.h>
#include <net/netns/unix.h>
@@ -131,14 +132,6 @@ struct net {
atomic_t fnhe_genid;
};
-/*
- * ifindex generation is per-net namespace, and loopback is
- * always the 1st device in ns (see net_dev_init), thus any
- * loopback device should get ifindex 1
- */
-
-#define LOOPBACK_IFINDEX 1
-
#include <linux/seq_file_net.h>
/* Init's network namespace */
diff --git a/include/net/netfilter/nf_tables_core.h b/include/net/netfilter/nf_tables_core.h
index cf2b7ae2b9d8..a75fc8e27cd6 100644
--- a/include/net/netfilter/nf_tables_core.h
+++ b/include/net/netfilter/nf_tables_core.h
@@ -13,6 +13,16 @@ struct nft_cmp_fast_expr {
u8 len;
};
+/* Calculate the mask for the nft_cmp_fast expression. On big endian the
+ * mask needs to include the *upper* bytes when interpreting that data as
+ * something smaller than the full u32, therefore a cpu_to_le32 is done.
+ */
+static inline u32 nft_cmp_fast_mask(unsigned int len)
+{
+ return cpu_to_le32(~0U >> (FIELD_SIZEOF(struct nft_cmp_fast_expr,
+ data) * BITS_PER_BYTE - len));
+}
+
extern const struct nft_expr_ops nft_cmp_fast_ops;
int nft_cmp_module_init(void);
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index 80f500a29498..b2704fd0ec80 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -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;
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 6ee76c804893..0dfcc92600e8 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1241,6 +1241,7 @@ struct sctp_endpoint {
/* SCTP-AUTH: endpoint shared keys */
struct list_head endpoint_shared_keys;
__u16 active_key_id;
+ __u8 auth_enable;
};
/* Recover the outter endpoint structure. */
@@ -1269,7 +1270,8 @@ struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *,
int sctp_has_association(struct net *net, const union sctp_addr *laddr,
const union sctp_addr *paddr);
-int sctp_verify_init(struct net *net, const struct sctp_association *asoc,
+int sctp_verify_init(struct net *net, const struct sctp_endpoint *ep,
+ const struct sctp_association *asoc,
sctp_cid_t, sctp_init_chunk_t *peer_init,
struct sctp_chunk *chunk, struct sctp_chunk **err_chunk);
int sctp_process_init(struct sctp_association *, struct sctp_chunk *chunk,
@@ -1653,6 +1655,17 @@ struct sctp_association {
/* This is the last advertised value of rwnd over a SACK chunk. */
__u32 a_rwnd;
+ /* Number of bytes by which the rwnd has slopped. The rwnd is allowed
+ * to slop over a maximum of the association's frag_point.
+ */
+ __u32 rwnd_over;
+
+ /* Keeps treack of rwnd pressure. This happens when we have
+ * a window, but not recevie buffer (i.e small packets). This one
+ * is releases slowly (1 PMTU at a time ).
+ */
+ __u32 rwnd_press;
+
/* This is the sndbuf size in use for the association.
* This corresponds to the sndbuf size for the association,
* as specified in the sk->sndbuf.
@@ -1881,7 +1894,8 @@ void sctp_assoc_update(struct sctp_association *old,
__u32 sctp_association_get_next_tsn(struct sctp_association *);
void sctp_assoc_sync_pmtu(struct sock *, struct sctp_association *);
-void sctp_assoc_rwnd_update(struct sctp_association *, bool);
+void sctp_assoc_rwnd_increase(struct sctp_association *, unsigned int);
+void sctp_assoc_rwnd_decrease(struct sctp_association *, unsigned int);
void sctp_assoc_set_primary(struct sctp_association *,
struct sctp_transport *);
void sctp_assoc_del_nonprimary_peers(struct sctp_association *,
diff --git a/include/net/sock.h b/include/net/sock.h
index 8338a14e4805..21569cf456ed 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -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
*/
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 32682ae47b3f..116e9c7e19cb 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -333,7 +333,7 @@ struct xfrm_state_afinfo {
const xfrm_address_t *saddr);
int (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n);
int (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n);
- int (*output)(struct sk_buff *skb);
+ int (*output)(struct sock *sk, struct sk_buff *skb);
int (*output_finish)(struct sk_buff *skb);
int (*extract_input)(struct xfrm_state *x,
struct sk_buff *skb);
@@ -1540,7 +1540,7 @@ static inline int xfrm4_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb);
int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb);
-int xfrm4_output(struct sk_buff *skb);
+int xfrm4_output(struct sock *sk, struct sk_buff *skb);
int xfrm4_output_finish(struct sk_buff *skb);
int xfrm4_rcv_cb(struct sk_buff *skb, u8 protocol, int err);
int xfrm4_protocol_register(struct xfrm4_protocol *handler, unsigned char protocol);
@@ -1565,7 +1565,7 @@ __be32 xfrm6_tunnel_alloc_spi(struct net *net, xfrm_address_t *saddr);
__be32 xfrm6_tunnel_spi_lookup(struct net *net, const xfrm_address_t *saddr);
int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb);
int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb);
-int xfrm6_output(struct sk_buff *skb);
+int xfrm6_output(struct sock *sk, struct sk_buff *skb);
int xfrm6_output_finish(struct sk_buff *skb);
int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb,
u8 **prevhdr);
diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
index 010ea89eeb0e..6a1a0245474f 100644
--- a/include/trace/events/ext4.h
+++ b/include/trace/events/ext4.h
@@ -16,15 +16,6 @@ struct mpage_da_data;
struct ext4_map_blocks;
struct extent_status;
-/* shim until we merge in the xfs_collapse_range branch */
-#ifndef FALLOC_FL_COLLAPSE_RANGE
-#define FALLOC_FL_COLLAPSE_RANGE 0x08
-#endif
-
-#ifndef FALLOC_FL_ZERO_RANGE
-#define FALLOC_FL_ZERO_RANGE 0x10
-#endif
-
#define EXT4_I(inode) (container_of(inode, struct ext4_inode_info, vfs_inode))
#define show_mballoc_flags(flags) __print_flags(flags, "|", \
diff --git a/include/trace/events/module.h b/include/trace/events/module.h
index 11fd51b413de..7c5cbfe3fc49 100644
--- a/include/trace/events/module.h
+++ b/include/trace/events/module.h
@@ -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);
),
diff --git a/include/uapi/asm-generic/fcntl.h b/include/uapi/asm-generic/fcntl.h
index a9b13f8b3595..7543b3e51331 100644
--- a/include/uapi/asm-generic/fcntl.h
+++ b/include/uapi/asm-generic/fcntl.h
@@ -133,20 +133,20 @@
#endif
/*
- * fd "private" POSIX locks.
+ * Open File Description Locks
*
- * Usually POSIX locks held by a process are released on *any* close and are
+ * Usually record locks held by a process are released on *any* close and are
* not inherited across a fork().
*
- * These cmd values will set locks that conflict with normal POSIX locks, but
- * are "owned" by the opened file, not the process. This means that they are
- * inherited across fork() like BSD (flock) locks, and they are only released
- * automatically when the last reference to the the open file against which
- * they were acquired is put.
+ * These cmd values will set locks that conflict with process-associated
+ * record locks, but are "owned" by the open file description, not the
+ * process. This means that they are inherited across fork() like BSD (flock)
+ * locks, and they are only released automatically when the last reference to
+ * the the open file against which they were acquired is put.
*/
-#define F_GETLKP 36
-#define F_SETLKP 37
-#define F_SETLKPW 38
+#define F_OFD_GETLK 36
+#define F_OFD_SETLK 37
+#define F_OFD_SETLKW 38
#define F_OWNER_TID 0
#define F_OWNER_PID 1
diff --git a/include/uapi/asm-generic/resource.h b/include/uapi/asm-generic/resource.h
index f863428796d5..c6d10af50123 100644
--- a/include/uapi/asm-generic/resource.h
+++ b/include/uapi/asm-generic/resource.h
@@ -57,12 +57,5 @@
# 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 */
diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
index 6db66783d268..333640608087 100644
--- a/include/uapi/asm-generic/unistd.h
+++ b/include/uapi/asm-generic/unistd.h
@@ -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,
diff --git a/include/uapi/drm/tegra_drm.h b/include/uapi/drm/tegra_drm.h
index b042b48495d9..b75482112428 100644
--- a/include/uapi/drm/tegra_drm.h
+++ b/include/uapi/drm/tegra_drm.h
@@ -120,7 +120,6 @@ struct drm_tegra_submit {
__u32 num_waitchks;
__u32 waitchk_mask;
__u32 timeout;
- __u32 pad;
__u64 syncpts;
__u64 cmdbufs;
__u64 relocs;
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index 11917f747cb4..4c31a366be16 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -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)
diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h
index cf4750e1bb49..40b5ca8a1b1f 100644
--- a/include/uapi/linux/fuse.h
+++ b/include/uapi/linux/fuse.h
@@ -96,6 +96,11 @@
*
* 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
diff --git a/include/uapi/linux/hyperv.h b/include/uapi/linux/hyperv.h
index 9beb7c991638..78e4a86030dd 100644
--- a/include/uapi/linux/hyperv.h
+++ b/include/uapi/linux/hyperv.h
@@ -305,6 +305,7 @@ enum hv_kvp_exchg_pool {
#define HV_ERROR_DEVICE_NOT_CONNECTED 0x8007048F
#define HV_INVALIDARG 0x80070057
#define HV_GUID_NOTFOUND 0x80041002
+#define HV_ERROR_ALREADY_EXISTS 0x80070050
#define ADDR_FAMILY_NONE 0x00
#define ADDR_FAMILY_IPV4 0x01
diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h
index bd24470d24a2..f4849525519c 100644
--- a/include/uapi/linux/input.h
+++ b/include/uapi/linux/input.h
@@ -164,6 +164,7 @@ struct input_keymap_entry {
#define INPUT_PROP_DIRECT 0x01 /* direct input devices */
#define INPUT_PROP_BUTTONPAD 0x02 /* has button(s) under pad */
#define INPUT_PROP_SEMI_MT 0x03 /* touch rectangle only */
+#define INPUT_PROP_TOPBUTTONPAD 0x04 /* softbuttons at top of pad */
#define INPUT_PROP_MAX 0x1f
#define INPUT_PROP_CNT (INPUT_PROP_MAX + 1)
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 1ba9d626aa83..194c1eab04d8 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -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,
diff --git a/include/xen/interface/xen.h b/include/xen/interface/xen.h
index 0cd5ca333fac..de082130ba4b 100644
--- a/include/xen/interface/xen.h
+++ b/include/xen/interface/xen.h
@@ -275,9 +275,9 @@ DEFINE_GUEST_HANDLE_STRUCT(mmu_update);
* NB. The fields are natural register size for this architecture.
*/
struct multicall_entry {
- unsigned long op;
- long result;
- unsigned long args[6];
+ xen_ulong_t op;
+ xen_long_t result;
+ xen_ulong_t args[6];
};
DEFINE_GUEST_HANDLE_STRUCT(multicall_entry);
diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h
index 2cf47175b12b..0b3149ed7eaa 100644
--- a/include/xen/xen-ops.h
+++ b/include/xen/xen-ops.h
@@ -9,10 +9,6 @@ DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu);
void xen_arch_pre_suspend(void);
void xen_arch_post_suspend(int suspend_cancelled);
-void xen_arch_hvm_post_suspend(int suspend_cancelled);
-
-void xen_mm_pin_all(void);
-void xen_mm_unpin_all(void);
void xen_timer_resume(void);
void xen_arch_resume(void);
diff --git a/init/Kconfig b/init/Kconfig
index 765018c24cf9..9d3585bb2a7a 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1646,6 +1646,18 @@ config MMAP_ALLOW_UNINITIALIZED
See Documentation/nommu-mmap.txt for more information.
+config SYSTEM_TRUSTED_KEYRING
+ bool "Provide system-wide ring of trusted keys"
+ depends on KEYS
+ help
+ Provide a system keyring to which trusted keys can be added. Keys in
+ the keyring are considered to be trusted. Keys may be added at will
+ by the kernel from compiled-in data and from hardware key stores, but
+ userspace may only add extra keys if those keys can be verified by
+ keys already in the keyring.
+
+ Keys in this keyring are used by module signature checking.
+
config PROFILING
bool "Profiling support"
help
@@ -1681,18 +1693,6 @@ config BASE_SMALL
default 0 if BASE_FULL
default 1 if !BASE_FULL
-config SYSTEM_TRUSTED_KEYRING
- bool "Provide system-wide ring of trusted keys"
- depends on KEYS
- help
- Provide a system keyring to which trusted keys can be added. Keys in
- the keyring are considered to be trusted. Keys may be added at will
- by the kernel from compiled-in data and from hardware key stores, but
- userspace may only add extra keys if those keys can be verified by
- keys already in the keyring.
-
- Keys in this keyring are used by module signature checking.
-
menuconfig MODULES
bool "Enable loadable module support"
option modules
diff --git a/init/main.c b/init/main.c
index 9c7fd4c9249f..48655ceb66f4 100644
--- a/init/main.c
+++ b/init/main.c
@@ -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[];
diff --git a/kernel/audit.c b/kernel/audit.c
index 7c2893602d06..47845c57eb19 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -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 */
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 9fcdaa705b6c..3f1ca934a237 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -348,7 +348,7 @@ struct cgrp_cset_link {
* reference-counted, to improve performance when child cgroups
* haven't been created.
*/
-static struct css_set init_css_set = {
+struct css_set init_css_set = {
.refcount = ATOMIC_INIT(1),
.cgrp_links = LIST_HEAD_INIT(init_css_set.cgrp_links),
.tasks = LIST_HEAD_INIT(init_css_set.tasks),
@@ -1495,7 +1495,7 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
*/
if (!use_task_css_set_links)
cgroup_enable_task_cg_lists();
-retry:
+
mutex_lock(&cgroup_tree_mutex);
mutex_lock(&cgroup_mutex);
@@ -1503,7 +1503,7 @@ retry:
ret = parse_cgroupfs_options(data, &opts);
if (ret)
goto out_unlock;
-
+retry:
/* look for a matching existing root */
if (!opts.subsys_mask && !opts.none && !opts.name) {
cgrp_dfl_root_visible = true;
@@ -1562,9 +1562,9 @@ retry:
if (!atomic_inc_not_zero(&root->cgrp.refcnt)) {
mutex_unlock(&cgroup_mutex);
mutex_unlock(&cgroup_tree_mutex);
- kfree(opts.release_agent);
- kfree(opts.name);
msleep(10);
+ mutex_lock(&cgroup_tree_mutex);
+ mutex_lock(&cgroup_mutex);
goto retry;
}
diff --git a/kernel/cgroup_freezer.c b/kernel/cgroup_freezer.c
index 2bc4a2256444..345628c78b5b 100644
--- a/kernel/cgroup_freezer.c
+++ b/kernel/cgroup_freezer.c
@@ -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,
diff --git a/kernel/context_tracking.c b/kernel/context_tracking.c
index 6cb20d2e7ee0..019d45008448 100644
--- a/kernel/context_tracking.c
+++ b/kernel/context_tracking.c
@@ -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;
diff --git a/kernel/cpu.c b/kernel/cpu.c
index a9e710eef0e2..247979a1b815 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -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)
diff --git a/kernel/events/core.c b/kernel/events/core.c
index f83a71a3e46d..440eefc67397 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -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);
}
diff --git a/kernel/futex.c b/kernel/futex.c
index 5f589279e462..81dbe773ce4c 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -745,7 +745,8 @@ void exit_pi_state_list(struct task_struct *curr)
static int
lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
- union futex_key *key, struct futex_pi_state **ps)
+ union futex_key *key, struct futex_pi_state **ps,
+ struct task_struct *task)
{
struct futex_pi_state *pi_state = NULL;
struct futex_q *this, *next;
@@ -786,6 +787,16 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
return -EINVAL;
}
+ /*
+ * Protect against a corrupted uval. If uval
+ * is 0x80000000 then pid is 0 and the waiter
+ * bit is set. So the deadlock check in the
+ * calling code has failed and we did not fall
+ * into the check above due to !pid.
+ */
+ if (task && pi_state->owner == task)
+ return -EDEADLK;
+
atomic_inc(&pi_state->refcount);
*ps = pi_state;
@@ -803,6 +814,11 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
if (!p)
return -ESRCH;
+ if (!p->mm) {
+ put_task_struct(p);
+ return -EPERM;
+ }
+
/*
* We need to look at the task state flags to figure out,
* whether the task is exiting. To protect against the do_exit
@@ -935,7 +951,7 @@ retry:
* We dont have the lock. Look up the PI state (or create it if
* we are the first waiter):
*/
- ret = lookup_pi_state(uval, hb, key, ps);
+ ret = lookup_pi_state(uval, hb, key, ps, task);
if (unlikely(ret)) {
switch (ret) {
@@ -1347,7 +1363,7 @@ void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key,
*
* Return:
* 0 - failed to acquire the lock atomically;
- * 1 - acquired the lock;
+ * >0 - acquired the lock, return value is vpid of the top_waiter
* <0 - error
*/
static int futex_proxy_trylock_atomic(u32 __user *pifutex,
@@ -1358,7 +1374,7 @@ static int futex_proxy_trylock_atomic(u32 __user *pifutex,
{
struct futex_q *top_waiter = NULL;
u32 curval;
- int ret;
+ int ret, vpid;
if (get_futex_value_locked(&curval, pifutex))
return -EFAULT;
@@ -1386,11 +1402,13 @@ static int futex_proxy_trylock_atomic(u32 __user *pifutex,
* the contended case or if set_waiters is 1. The pi_state is returned
* in ps in contended cases.
*/
+ vpid = task_pid_vnr(top_waiter->task);
ret = futex_lock_pi_atomic(pifutex, hb2, key2, ps, top_waiter->task,
set_waiters);
- if (ret == 1)
+ if (ret == 1) {
requeue_pi_wake_futex(top_waiter, key2, hb2);
-
+ return vpid;
+ }
return ret;
}
@@ -1421,7 +1439,6 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
struct futex_pi_state *pi_state = NULL;
struct futex_hash_bucket *hb1, *hb2;
struct futex_q *this, *next;
- u32 curval2;
if (requeue_pi) {
/*
@@ -1509,16 +1526,25 @@ retry_private:
* At this point the top_waiter has either taken uaddr2 or is
* waiting on it. If the former, then the pi_state will not
* exist yet, look it up one more time to ensure we have a
- * reference to it.
+ * reference to it. If the lock was taken, ret contains the
+ * vpid of the top waiter task.
*/
- if (ret == 1) {
+ if (ret > 0) {
WARN_ON(pi_state);
drop_count++;
task_count++;
- ret = get_futex_value_locked(&curval2, uaddr2);
- if (!ret)
- ret = lookup_pi_state(curval2, hb2, &key2,
- &pi_state);
+ /*
+ * If we acquired the lock, then the user
+ * space value of uaddr2 should be vpid. It
+ * cannot be changed by the top waiter as it
+ * is blocked on hb2 lock if it tries to do
+ * so. If something fiddled with it behind our
+ * back the pi state lookup might unearth
+ * it. So we rather use the known value than
+ * rereading and handing potential crap to
+ * lookup_pi_state.
+ */
+ ret = lookup_pi_state(ret, hb2, &key2, &pi_state, NULL);
}
switch (ret) {
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index d55092ceee29..e0501fe7140d 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -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);
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
index a7174617616b..bb07f2928f4b 100644
--- a/kernel/irq/irqdesc.c
+++ b/kernel/irq/irqdesc.c
@@ -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);
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 2486a4c1a710..d34131ca372b 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -180,7 +180,7 @@ int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask,
struct irq_chip *chip = irq_data_get_irq_chip(data);
int ret;
- ret = chip->irq_set_affinity(data, mask, false);
+ ret = chip->irq_set_affinity(data, mask, force);
switch (ret) {
case IRQ_SET_MASK_OK:
cpumask_copy(data->affinity, mask);
@@ -192,7 +192,8 @@ int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask,
return ret;
}
-int __irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask)
+int irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask,
+ bool force)
{
struct irq_chip *chip = irq_data_get_irq_chip(data);
struct irq_desc *desc = irq_data_to_desc(data);
@@ -202,7 +203,7 @@ int __irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask)
return -EINVAL;
if (irq_can_move_pcntxt(data)) {
- ret = irq_do_set_affinity(data, mask, false);
+ ret = irq_do_set_affinity(data, mask, force);
} else {
irqd_set_move_pending(data);
irq_copy_pending(desc, mask);
@@ -217,13 +218,7 @@ int __irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask)
return ret;
}
-/**
- * irq_set_affinity - Set the irq affinity of a given irq
- * @irq: Interrupt to set affinity
- * @mask: cpumask
- *
- */
-int irq_set_affinity(unsigned int irq, const struct cpumask *mask)
+int __irq_set_affinity(unsigned int irq, const struct cpumask *mask, bool force)
{
struct irq_desc *desc = irq_to_desc(irq);
unsigned long flags;
@@ -233,7 +228,7 @@ int irq_set_affinity(unsigned int irq, const struct cpumask *mask)
return -EINVAL;
raw_spin_lock_irqsave(&desc->lock, flags);
- ret = __irq_set_affinity_locked(irq_desc_get_irq_data(desc), mask);
+ ret = irq_set_affinity_locked(irq_desc_get_irq_data(desc), mask, force);
raw_spin_unlock_irqrestore(&desc->lock, flags);
return ret;
}
diff --git a/kernel/kexec.c b/kernel/kexec.c
index c8380ad203bc..28c57069ef68 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -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();
}
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
index b0e9467922e1..d24e4339b46d 100644
--- a/kernel/locking/lockdep.c
+++ b/kernel/locking/lockdep.c
@@ -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;
diff --git a/kernel/locking/mutex-debug.c b/kernel/locking/mutex-debug.c
index e1191c996c59..5cf6731b98e9 100644
--- a/kernel/locking/mutex-debug.c
+++ b/kernel/locking/mutex-debug.c
@@ -71,18 +71,17 @@ void mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter,
void debug_mutex_unlock(struct mutex *lock)
{
- if (unlikely(!debug_locks))
- return;
+ if (likely(debug_locks)) {
+ DEBUG_LOCKS_WARN_ON(lock->magic != lock);
- DEBUG_LOCKS_WARN_ON(lock->magic != lock);
+ if (!lock->owner)
+ DEBUG_LOCKS_WARN_ON(!lock->owner);
+ else
+ DEBUG_LOCKS_WARN_ON(lock->owner != current);
- if (!lock->owner)
- DEBUG_LOCKS_WARN_ON(!lock->owner);
- else
- DEBUG_LOCKS_WARN_ON(lock->owner != current);
-
- DEBUG_LOCKS_WARN_ON(!lock->wait_list.prev && !lock->wait_list.next);
- mutex_clear_owner(lock);
+ DEBUG_LOCKS_WARN_ON(!lock->wait_list.prev && !lock->wait_list.next);
+ mutex_clear_owner(lock);
+ }
/*
* __mutex_slowpath_needs_to_unlock() is explicitly 0 for debug
diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c
index aa4dff04b594..a620d4d08ca6 100644
--- a/kernel/locking/rtmutex.c
+++ b/kernel/locking/rtmutex.c
@@ -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;
diff --git a/kernel/module.c b/kernel/module.c
index 11869408f79b..079c4615607d 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -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)
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index 18fb7a2fb14b..1ea328aafdc9 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -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;
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index c3ad9cafe930..8233cd4047d7 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -14,6 +14,7 @@
#include <linux/init.h>
#include <linux/console.h>
#include <linux/cpu.h>
+#include <linux/cpuidle.h>
#include <linux/syscalls.h>
#include <linux/gfp.h>
#include <linux/io.h>
@@ -53,7 +54,9 @@ static void freeze_begin(void)
static void freeze_enter(void)
{
+ cpuidle_resume();
wait_event(suspend_freeze_wait_head, suspend_freeze_wake);
+ cpuidle_pause();
}
void freeze_wake(void)
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index a45b50962295..7228258b85ec 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -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;
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 268a45ea238c..0a7251678982 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -2192,7 +2192,7 @@ static inline void post_schedule(struct rq *rq)
* schedule_tail - first thing a freshly forked thread must call.
* @prev: the thread we just switched away from.
*/
-asmlinkage void schedule_tail(struct task_struct *prev)
+asmlinkage __visible void schedule_tail(struct task_struct *prev)
__releases(rq->lock)
{
struct rq *rq = this_rq();
@@ -2592,8 +2592,14 @@ pick_next_task(struct rq *rq, struct task_struct *prev)
if (likely(prev->sched_class == class &&
rq->nr_running == rq->cfs.h_nr_running)) {
p = fair_sched_class.pick_next_task(rq, prev);
- if (likely(p && p != RETRY_TASK))
- return p;
+ if (unlikely(p == RETRY_TASK))
+ goto again;
+
+ /* assumes fair_sched_class->next == idle_sched_class */
+ if (unlikely(!p))
+ p = idle_sched_class.pick_next_task(rq, prev);
+
+ return p;
}
again:
@@ -2741,7 +2747,7 @@ static inline void sched_submit_work(struct task_struct *tsk)
blk_schedule_flush_plug(tsk);
}
-asmlinkage void __sched schedule(void)
+asmlinkage __visible void __sched schedule(void)
{
struct task_struct *tsk = current;
@@ -2751,7 +2757,7 @@ asmlinkage void __sched schedule(void)
EXPORT_SYMBOL(schedule);
#ifdef CONFIG_CONTEXT_TRACKING
-asmlinkage void __sched schedule_user(void)
+asmlinkage __visible void __sched schedule_user(void)
{
/*
* If we come here after a random call to set_need_resched(),
@@ -2783,7 +2789,7 @@ void __sched schedule_preempt_disabled(void)
* off of preempt_enable. Kernel preemptions off return from interrupt
* occur there and call schedule directly.
*/
-asmlinkage void __sched notrace preempt_schedule(void)
+asmlinkage __visible void __sched notrace preempt_schedule(void)
{
/*
* If there is a non-zero preempt_count or interrupts are disabled,
@@ -2813,7 +2819,7 @@ EXPORT_SYMBOL(preempt_schedule);
* Note, that this is called and return with irqs disabled. This will
* protect us against recursive calling from irq.
*/
-asmlinkage void __sched preempt_schedule_irq(void)
+asmlinkage __visible void __sched preempt_schedule_irq(void)
{
enum ctx_state prev_state;
@@ -3124,6 +3130,7 @@ __setparam_dl(struct task_struct *p, const struct sched_attr *attr)
dl_se->dl_bw = to_ratio(dl_se->dl_period, dl_se->dl_runtime);
dl_se->dl_throttled = 0;
dl_se->dl_new = 1;
+ dl_se->dl_yielded = 0;
}
static void __setscheduler_params(struct task_struct *p,
@@ -3188,17 +3195,40 @@ __getparam_dl(struct task_struct *p, struct sched_attr *attr)
* We ask for the deadline not being zero, and greater or equal
* than the runtime, as well as the period of being zero or
* greater than deadline. Furthermore, we have to be sure that
- * user parameters are above the internal resolution (1us); we
- * check sched_runtime only since it is always the smaller one.
+ * user parameters are above the internal resolution of 1us (we
+ * check sched_runtime only since it is always the smaller one) and
+ * below 2^63 ns (we have to check both sched_deadline and
+ * sched_period, as the latter can be zero).
*/
static bool
__checkparam_dl(const struct sched_attr *attr)
{
- return attr && attr->sched_deadline != 0 &&
- (attr->sched_period == 0 ||
- (s64)(attr->sched_period - attr->sched_deadline) >= 0) &&
- (s64)(attr->sched_deadline - attr->sched_runtime ) >= 0 &&
- attr->sched_runtime >= (2 << (DL_SCALE - 1));
+ /* deadline != 0 */
+ if (attr->sched_deadline == 0)
+ return false;
+
+ /*
+ * Since we truncate DL_SCALE bits, make sure we're at least
+ * that big.
+ */
+ if (attr->sched_runtime < (1ULL << DL_SCALE))
+ return false;
+
+ /*
+ * Since we use the MSB for wrap-around and sign issues, make
+ * sure it's not set (mind that period can be equal to zero).
+ */
+ if (attr->sched_deadline & (1ULL << 63) ||
+ attr->sched_period & (1ULL << 63))
+ return false;
+
+ /* runtime <= deadline <= period (if period != 0) */
+ if ((attr->sched_period != 0 &&
+ attr->sched_period < attr->sched_deadline) ||
+ attr->sched_deadline < attr->sched_runtime)
+ return false;
+
+ return true;
}
/*
@@ -3639,6 +3669,7 @@ SYSCALL_DEFINE2(sched_setparam, pid_t, pid, struct sched_param __user *, param)
* sys_sched_setattr - same as above, but with extended sched_attr
* @pid: the pid in question.
* @uattr: structure containing the extended parameters.
+ * @flags: for future extension.
*/
SYSCALL_DEFINE3(sched_setattr, pid_t, pid, struct sched_attr __user *, uattr,
unsigned int, flags)
@@ -3650,8 +3681,12 @@ SYSCALL_DEFINE3(sched_setattr, pid_t, pid, struct sched_attr __user *, uattr,
if (!uattr || pid < 0 || flags)
return -EINVAL;
- if (sched_copy_attr(uattr, &attr))
- return -EFAULT;
+ retval = sched_copy_attr(uattr, &attr);
+ if (retval)
+ return retval;
+
+ if (attr.sched_policy < 0)
+ return -EINVAL;
rcu_read_lock();
retval = -ESRCH;
@@ -3701,7 +3736,7 @@ SYSCALL_DEFINE1(sched_getscheduler, pid_t, pid)
*/
SYSCALL_DEFINE2(sched_getparam, pid_t, pid, struct sched_param __user *, param)
{
- struct sched_param lp;
+ struct sched_param lp = { .sched_priority = 0 };
struct task_struct *p;
int retval;
@@ -3718,11 +3753,8 @@ SYSCALL_DEFINE2(sched_getparam, pid_t, pid, struct sched_param __user *, param)
if (retval)
goto out_unlock;
- if (task_has_dl_policy(p)) {
- retval = -EINVAL;
- goto out_unlock;
- }
- lp.sched_priority = p->rt_priority;
+ if (task_has_rt_policy(p))
+ lp.sched_priority = p->rt_priority;
rcu_read_unlock();
/*
@@ -3783,6 +3815,7 @@ err_size:
* @pid: the pid in question.
* @uattr: structure containing the extended parameters.
* @size: sizeof(attr) for fwd/bwd comp.
+ * @flags: for future extension.
*/
SYSCALL_DEFINE4(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr,
unsigned int, size, unsigned int, flags)
@@ -5043,7 +5076,6 @@ static int sched_cpu_active(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
switch (action & ~CPU_TASKS_FROZEN) {
- case CPU_STARTING:
case CPU_DOWN_FAILED:
set_cpu_active((long)hcpu, true);
return NOTIFY_OK;
@@ -6017,6 +6049,8 @@ sd_numa_init(struct sched_domain_topology_level *tl, int cpu)
,
.last_balance = jiffies,
.balance_interval = sd_weight,
+ .max_newidle_lb_cost = 0,
+ .next_decay_max_lb_cost = jiffies,
};
SD_INIT_NAME(sd, NUMA);
sd->private = &tl->data;
diff --git a/kernel/sched/cpudeadline.c b/kernel/sched/cpudeadline.c
index 5b9bb42b2d47..bd95963dae80 100644
--- a/kernel/sched/cpudeadline.c
+++ b/kernel/sched/cpudeadline.c
@@ -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);
}
diff --git a/kernel/sched/cpudeadline.h b/kernel/sched/cpudeadline.h
index a202789a412c..538c9796ad4a 100644
--- a/kernel/sched/cpudeadline.h
+++ b/kernel/sched/cpudeadline.h
@@ -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;
};
diff --git a/kernel/sched/cpupri.c b/kernel/sched/cpupri.c
index 8b836b376d91..8834243abee2 100644
--- a/kernel/sched/cpupri.c
+++ b/kernel/sched/cpupri.c
@@ -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);
}
diff --git a/kernel/sched/cpupri.h b/kernel/sched/cpupri.h
index f6d756173491..6b033347fdfd 100644
--- a/kernel/sched/cpupri.h
+++ b/kernel/sched/cpupri.h
@@ -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
diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c
index a95097cb4591..72fdf06ef865 100644
--- a/kernel/sched/cputime.c
+++ b/kernel/sched/cputime.c
@@ -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, cputime, scaled);
} 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, cputime, scaled);
} 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;
}
diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
index 27ef40925525..800e99b99075 100644
--- a/kernel/sched/deadline.c
+++ b/kernel/sched/deadline.c
@@ -528,6 +528,7 @@ static enum hrtimer_restart dl_task_timer(struct hrtimer *timer)
sched_clock_tick();
update_rq_clock(rq);
dl_se->dl_throttled = 0;
+ dl_se->dl_yielded = 0;
if (p->on_rq) {
enqueue_task_dl(rq, p, ENQUEUE_REPLENISH);
if (task_has_dl_policy(rq->curr))
@@ -893,10 +894,10 @@ static void yield_task_dl(struct rq *rq)
* We make the task go to sleep until its current deadline by
* forcing its runtime to zero. This way, update_curr_dl() stops
* it and the bandwidth timer will wake it up and will give it
- * new scheduling parameters (thanks to dl_new=1).
+ * new scheduling parameters (thanks to dl_yielded=1).
*/
if (p->dl.runtime > 0) {
- rq->curr->dl.dl_new = 1;
+ rq->curr->dl.dl_yielded = 1;
p->dl.runtime = 0;
}
update_curr_dl(rq);
@@ -1021,8 +1022,17 @@ struct task_struct *pick_next_task_dl(struct rq *rq, struct task_struct *prev)
dl_rq = &rq->dl;
- if (need_pull_dl_task(rq, prev))
+ if (need_pull_dl_task(rq, prev)) {
pull_dl_task(rq);
+ /*
+ * pull_rt_task() can drop (and re-acquire) rq->lock; this
+ * means a stop task can slip in, in which case we need to
+ * re-start task selection.
+ */
+ if (rq->stop && rq->stop->on_rq)
+ return RETRY_TASK;
+ }
+
/*
* When prev is DL, we may throttle it in put_prev_task().
* So, we update time before we check for dl_nr_running.
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 7e9bd0b1fa9e..0fdb96de81a5 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -1497,7 +1497,7 @@ static void task_numa_placement(struct task_struct *p)
/* If the task is part of a group prevent parallel updates to group stats */
if (p->numa_group) {
group_lock = &p->numa_group->lock;
- spin_lock(group_lock);
+ spin_lock_irq(group_lock);
}
/* Find the node with the highest number of faults */
@@ -1572,7 +1572,7 @@ static void task_numa_placement(struct task_struct *p)
}
}
- spin_unlock(group_lock);
+ spin_unlock_irq(group_lock);
}
/* Preferred node as the node with the most faults */
@@ -1677,7 +1677,8 @@ static void task_numa_group(struct task_struct *p, int cpupid, int flags,
if (!join)
return;
- double_lock(&my_grp->lock, &grp->lock);
+ BUG_ON(irqs_disabled());
+ double_lock_irq(&my_grp->lock, &grp->lock);
for (i = 0; i < NR_NUMA_HINT_FAULT_STATS * nr_node_ids; i++) {
my_grp->faults[i] -= p->numa_faults_memory[i];
@@ -1691,7 +1692,7 @@ static void task_numa_group(struct task_struct *p, int cpupid, int flags,
grp->nr_tasks++;
spin_unlock(&my_grp->lock);
- spin_unlock(&grp->lock);
+ spin_unlock_irq(&grp->lock);
rcu_assign_pointer(p->numa_group, grp);
@@ -1710,14 +1711,14 @@ void task_numa_free(struct task_struct *p)
void *numa_faults = p->numa_faults_memory;
if (grp) {
- spin_lock(&grp->lock);
+ spin_lock_irq(&grp->lock);
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(&grp->lock);
+ spin_unlock_irq(&grp->lock);
rcu_assign_pointer(p->numa_group, NULL);
put_numa_group(grp);
}
@@ -6652,6 +6653,7 @@ static int idle_balance(struct rq *this_rq)
int this_cpu = this_rq->cpu;
idle_enter_fair(this_rq);
+
/*
* We must set idle_stamp _before_ calling idle_balance(), such that we
* measure the duration of idle_balance() as idle time.
@@ -6704,14 +6706,16 @@ static int idle_balance(struct rq *this_rq)
raw_spin_lock(&this_rq->lock);
+ if (curr_cost > this_rq->max_idle_balance_cost)
+ this_rq->max_idle_balance_cost = curr_cost;
+
/*
- * While browsing the domains, we released the rq lock.
- * A task could have be enqueued in the meantime
+ * While browsing the domains, we released the rq lock, a task could
+ * have been enqueued in the meantime. Since we're not going idle,
+ * pretend we pulled a task.
*/
- if (this_rq->cfs.h_nr_running && !pulled_task) {
+ if (this_rq->cfs.h_nr_running && !pulled_task)
pulled_task = 1;
- goto out;
- }
if (pulled_task || time_after(jiffies, this_rq->next_balance)) {
/*
@@ -6721,13 +6725,11 @@ 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 &&
- (this_rq->dl.dl_nr_running ||
+ ((this_rq->stop && this_rq->stop->on_rq) ||
+ this_rq->dl.dl_nr_running ||
(this_rq->rt.rt_nr_running && !rt_rq_throttled(&this_rq->rt))))
pulled_task = -1;
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
index d8cdf1618551..bd2267ad404f 100644
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -1362,10 +1362,11 @@ pick_next_task_rt(struct rq *rq, struct task_struct *prev)
pull_rt_task(rq);
/*
* pull_rt_task() can drop (and re-acquire) rq->lock; this
- * means a dl task can slip in, in which case we need to
- * re-start task selection.
+ * means a dl or stop task can slip in, in which case we need
+ * to re-start task selection.
*/
- if (unlikely(rq->dl.dl_nr_running))
+ if (unlikely((rq->stop && rq->stop->on_rq) ||
+ rq->dl.dl_nr_running))
return RETRY_TASK;
}
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index c9007f28d3a2..456e492a3dca 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -1385,6 +1385,15 @@ static inline void double_lock(spinlock_t *l1, spinlock_t *l2)
spin_lock_nested(l2, SINGLE_DEPTH_NESTING);
}
+static inline void double_lock_irq(spinlock_t *l1, spinlock_t *l2)
+{
+ if (l1 > l2)
+ swap(l1, l2);
+
+ spin_lock_irq(l1);
+ spin_lock_nested(l2, SINGLE_DEPTH_NESTING);
+}
+
static inline void double_raw_lock(raw_spinlock_t *l1, raw_spinlock_t *l2)
{
if (l1 > l2)
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index d8d046c0726a..b35c21503a36 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -69,18 +69,17 @@ static void populate_seccomp_data(struct seccomp_data *sd)
{
struct task_struct *task = current;
struct pt_regs *regs = task_pt_regs(task);
+ unsigned long args[6];
sd->nr = syscall_get_nr(task, regs);
sd->arch = syscall_get_arch();
-
- /* Unroll syscall_get_args to help gcc on arm. */
- syscall_get_arguments(task, regs, 0, 1, (unsigned long *) &sd->args[0]);
- syscall_get_arguments(task, regs, 1, 1, (unsigned long *) &sd->args[1]);
- syscall_get_arguments(task, regs, 2, 1, (unsigned long *) &sd->args[2]);
- syscall_get_arguments(task, regs, 3, 1, (unsigned long *) &sd->args[3]);
- syscall_get_arguments(task, regs, 4, 1, (unsigned long *) &sd->args[4]);
- syscall_get_arguments(task, regs, 5, 1, (unsigned long *) &sd->args[5]);
-
+ syscall_get_arguments(task, regs, 0, 6, args);
+ sd->args[0] = args[0];
+ sd->args[1] = args[1];
+ sd->args[2] = args[2];
+ sd->args[3] = args[3];
+ sd->args[4] = args[4];
+ sd->args[5] = args[5];
sd->instruction_pointer = KSTK_EIP(task);
}
@@ -256,6 +255,7 @@ static long seccomp_attach_filter(struct sock_fprog *fprog)
goto free_prog;
/* Allocate a new seccomp_filter */
+ ret = -ENOMEM;
filter = kzalloc(sizeof(struct seccomp_filter) +
sizeof(struct sock_filter_int) * new_len,
GFP_KERNEL|__GFP_NOWARN);
@@ -265,6 +265,7 @@ static long seccomp_attach_filter(struct sock_fprog *fprog)
ret = sk_convert_filter(fp, fprog->len, filter->insnsi, &new_len);
if (ret)
goto free_filter;
+ kfree(fp);
atomic_set(&filter->usage, 1);
filter->len = new_len;
diff --git a/kernel/softirq.c b/kernel/softirq.c
index b50990a5bea0..92f24f5e8d52 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -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;
+}
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
index 015661279b68..0a0608edeb26 100644
--- a/kernel/time/tick-common.c
+++ b/kernel/time/tick-common.c
@@ -276,7 +276,7 @@ static bool tick_check_preferred(struct clock_event_device *curdev,
bool tick_check_replacement(struct clock_event_device *curdev,
struct clock_event_device *newdev)
{
- if (tick_check_percpu(curdev, newdev, smp_processor_id()))
+ if (!tick_check_percpu(curdev, newdev, smp_processor_id()))
return false;
return tick_check_preferred(curdev, newdev);
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 9f8af69c67ec..6558b7ac112d 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -84,6 +84,9 @@ static void tick_do_update_jiffies64(ktime_t now)
/* Keep the tick_next_period variable up to date */
tick_next_period = ktime_add(last_jiffies_update, tick_period);
+ } else {
+ write_sequnlock(&jiffies_lock);
+ return;
}
write_sequnlock(&jiffies_lock);
update_wall_time();
@@ -967,7 +970,7 @@ static void tick_nohz_switch_to_nohz(void)
struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
ktime_t next;
- if (!tick_nohz_active)
+ if (!tick_nohz_enabled)
return;
local_irq_disable();
diff --git a/kernel/timer.c b/kernel/timer.c
index 87bd529879c2..3bb01a323b2a 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -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);
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 1fd4b9479210..4a54a25afa2f 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -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");
diff --git a/kernel/trace/trace_events_trigger.c b/kernel/trace/trace_events_trigger.c
index 925f537f07d1..4747b476a030 100644
--- a/kernel/trace/trace_events_trigger.c
+++ b/kernel/trace/trace_events_trigger.c
@@ -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) {
diff --git a/kernel/trace/trace_functions.c b/kernel/trace/trace_functions.c
index 5b781d2be383..ffd56351b521 100644
--- a/kernel/trace/trace_functions.c
+++ b/kernel/trace/trace_functions.c
@@ -58,12 +58,16 @@ int ftrace_create_function_files(struct trace_array *tr,
{
int ret;
- /* The top level array uses the "global_ops". */
- if (!(tr->flags & TRACE_ARRAY_FL_GLOBAL)) {
- ret = allocate_ftrace_ops(tr);
- if (ret)
- return ret;
- }
+ /*
+ * The top level array uses the "global_ops", and the files are
+ * created on boot up.
+ */
+ if (tr->flags & TRACE_ARRAY_FL_GLOBAL)
+ return 0;
+
+ ret = allocate_ftrace_ops(tr);
+ if (ret)
+ return ret;
ftrace_create_filter_files(tr->ops, parent);
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
index 930e51462dc8..c082a7441345 100644
--- a/kernel/trace/trace_uprobe.c
+++ b/kernel/trace/trace_uprobe.c
@@ -732,9 +732,15 @@ static int uprobe_buffer_enable(void)
static void uprobe_buffer_disable(void)
{
+ int cpu;
+
BUG_ON(!mutex_is_locked(&event_mutex));
if (--uprobe_buffer_refcnt == 0) {
+ for_each_possible_cpu(cpu)
+ free_page((unsigned long)per_cpu_ptr(uprobe_cpu_buffer,
+ cpu)->buf);
+
free_percpu(uprobe_cpu_buffer);
uprobe_cpu_buffer = NULL;
}
diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c
index ac5b23cf7212..6620e5837ce2 100644
--- a/kernel/tracepoint.c
+++ b/kernel/tracepoint.c
@@ -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;
}
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index 0d8f6023fd8d..bf71b4b2d632 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -152,7 +152,7 @@ static u32 map_id_range_down(struct uid_gid_map *map, u32 id, u32 count)
/* Find the matching extent */
extents = map->nr_extents;
- smp_read_barrier_depends();
+ smp_rmb();
for (idx = 0; idx < extents; idx++) {
first = map->extent[idx].first;
last = first + map->extent[idx].count - 1;
@@ -176,7 +176,7 @@ static u32 map_id_down(struct uid_gid_map *map, u32 id)
/* Find the matching extent */
extents = map->nr_extents;
- smp_read_barrier_depends();
+ smp_rmb();
for (idx = 0; idx < extents; idx++) {
first = map->extent[idx].first;
last = first + map->extent[idx].count - 1;
@@ -199,7 +199,7 @@ static u32 map_id_up(struct uid_gid_map *map, u32 id)
/* Find the matching extent */
extents = map->nr_extents;
- smp_read_barrier_depends();
+ smp_rmb();
for (idx = 0; idx < extents; idx++) {
first = map->extent[idx].lower_first;
last = first + map->extent[idx].count - 1;
@@ -615,9 +615,8 @@ static ssize_t map_write(struct file *file, const char __user *buf,
* were written before the count of the extents.
*
* To achieve this smp_wmb() is used on guarantee the write
- * order and smp_read_barrier_depends() is guaranteed that we
- * don't have crazy architectures returning stale data.
- *
+ * order and smp_rmb() is guaranteed that we don't have crazy
+ * architectures returning stale data.
*/
mutex_lock(&id_map_mutex);
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index e90089fd78e0..516203e665fc 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -138,7 +138,11 @@ static void __touch_watchdog(void)
void touch_softlockup_watchdog(void)
{
- __this_cpu_write(watchdog_touch_ts, 0);
+ /*
+ * Preemption can be enabled. It doesn't matter which CPU's timestamp
+ * gets zeroed here, so use the raw_ operation.
+ */
+ raw_cpu_write(watchdog_touch_ts, 0);
}
EXPORT_SYMBOL(touch_softlockup_watchdog);
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 0ee63af30bd1..8edc87185427 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -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);
@@ -2445,6 +2456,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
* and stalling the execution.
@@ -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;
}
/*
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 140b66a874c1..819ac51202c0 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -505,8 +505,7 @@ config DEBUG_VM_RB
bool "Debug VM red-black trees"
depends on DEBUG_VM
help
- Enable this to turn on more extended checks in the virtual-memory
- system that may impact performance.
+ Enable VM red-black tree debugging information and extra validations.
If unsure, say N.
diff --git a/lib/dump_stack.c b/lib/dump_stack.c
index f23b63f0a1c3..6745c6230db3 100644
--- a/lib/dump_stack.c
+++ b/lib/dump_stack.c
@@ -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();
}
diff --git a/mm/Kconfig b/mm/Kconfig
index ebe5880c29d6..1b5a95f0fa01 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -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.
diff --git a/mm/compaction.c b/mm/compaction.c
index 37f976287068..627dc2e4320f 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -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;
diff --git a/mm/filemap.c b/mm/filemap.c
index a82fbe4c9e8e..088358c8006b 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -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))
@@ -2581,7 +2590,6 @@ EXPORT_SYMBOL(generic_perform_write);
* @iocb: IO state structure (file, offset, etc.)
* @iov: vector with data to write
* @nr_segs: number of segments in the vector
- * @ppos: position where to write
*
* This function does all the work needed for actually writing data to a
* file. It does all basic checks, removes SUID from the file, updates
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 64635f5278ff..b4b1feba6472 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1536,16 +1536,23 @@ pmd_t *page_check_address_pmd(struct page *page,
enum page_check_address_pmd_flag flag,
spinlock_t **ptl)
{
+ pgd_t *pgd;
+ pud_t *pud;
pmd_t *pmd;
if (address & ~HPAGE_PMD_MASK)
return NULL;
- pmd = mm_find_pmd(mm, address);
- if (!pmd)
+ pgd = pgd_offset(mm, address);
+ if (!pgd_present(*pgd))
return NULL;
+ pud = pud_offset(pgd, address);
+ if (!pud_present(*pud))
+ return NULL;
+ pmd = pmd_offset(pud, address);
+
*ptl = pmd_lock(mm, pmd);
- if (pmd_none(*pmd))
+ if (!pmd_present(*pmd))
goto unlock;
if (pmd_page(*pmd) != page)
goto unlock;
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index dd30f22b35e0..c82290b9c1fc 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -1172,6 +1172,7 @@ static void return_unused_surplus_pages(struct hstate *h,
while (nr_pages--) {
if (!free_pool_huge_page(h, &node_states[N_MEMORY], 1))
break;
+ cond_resched_lock(&hugetlb_lock);
}
}
@@ -1980,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)) {
@@ -2111,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)
@@ -2164,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)
@@ -2189,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"
@@ -2205,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"
@@ -2219,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",
diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index 91d67eaee050..8d2fcdfeff7f 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -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;
diff --git a/mm/madvise.c b/mm/madvise.c
index 539eeb96b323..a402f8fdc68e 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -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);
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 29501f040568..5177c6d4a2dd 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -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;
}
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 35ef28acf137..9ccef39a9de2 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -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;
}
diff --git a/mm/memory.c b/mm/memory.c
index d0f0bef3be48..037b812a9531 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -232,17 +232,18 @@ void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long
#endif
}
-void tlb_flush_mmu(struct mmu_gather *tlb)
+static void tlb_flush_mmu_tlbonly(struct mmu_gather *tlb)
{
- struct mmu_gather_batch *batch;
-
- if (!tlb->need_flush)
- return;
tlb->need_flush = 0;
tlb_flush(tlb);
#ifdef CONFIG_HAVE_RCU_TABLE_FREE
tlb_table_flush(tlb);
#endif
+}
+
+static void tlb_flush_mmu_free(struct mmu_gather *tlb)
+{
+ struct mmu_gather_batch *batch;
for (batch = &tlb->local; batch; batch = batch->next) {
free_pages_and_swap_cache(batch->pages, batch->nr);
@@ -251,6 +252,14 @@ void tlb_flush_mmu(struct mmu_gather *tlb)
tlb->active = &tlb->local;
}
+void tlb_flush_mmu(struct mmu_gather *tlb)
+{
+ if (!tlb->need_flush)
+ return;
+ tlb_flush_mmu_tlbonly(tlb);
+ tlb_flush_mmu_free(tlb);
+}
+
/* tlb_finish_mmu
* Called at the end of the shootdown operation to free up any resources
* that were required.
@@ -1127,8 +1136,10 @@ again:
if (PageAnon(page))
rss[MM_ANONPAGES]--;
else {
- if (pte_dirty(ptent))
+ if (pte_dirty(ptent)) {
+ force_flush = 1;
set_page_dirty(page);
+ }
if (pte_young(ptent) &&
likely(!(vma->vm_flags & VM_SEQ_READ)))
mark_page_accessed(page);
@@ -1137,9 +1148,10 @@ again:
page_remove_rmap(page);
if (unlikely(page_mapcount(page) < 0))
print_bad_pte(vma, addr, ptent, page);
- force_flush = !__tlb_remove_page(tlb, page);
- if (force_flush)
+ if (unlikely(!__tlb_remove_page(tlb, page))) {
+ force_flush = 1;
break;
+ }
continue;
}
/*
@@ -1174,18 +1186,11 @@ again:
add_mm_rss_vec(mm, rss);
arch_leave_lazy_mmu_mode();
- pte_unmap_unlock(start_pte, ptl);
- /*
- * mmu_gather ran out of room to batch pages, we break out of
- * the PTE lock to avoid doing the potential expensive TLB invalidate
- * and page-free while holding it.
- */
+ /* Do the actual TLB flush before dropping ptl */
if (force_flush) {
unsigned long old_end;
- force_flush = 0;
-
/*
* Flush the TLB just for the previous segment,
* then update the range to be the remaining
@@ -1193,11 +1198,21 @@ again:
*/
old_end = tlb->end;
tlb->end = addr;
-
- tlb_flush_mmu(tlb);
-
+ tlb_flush_mmu_tlbonly(tlb);
tlb->start = addr;
tlb->end = old_end;
+ }
+ pte_unmap_unlock(start_pte, ptl);
+
+ /*
+ * If we forced a TLB flush (either due to running out of
+ * batch buffers or because we needed to flush dirty TLB
+ * entries before releasing the ptl), free the batched
+ * memory too. Restart if we didn't do everything.
+ */
+ if (force_flush) {
+ force_flush = 0;
+ tlb_flush_mmu_free(tlb);
if (addr != end)
goto again;
@@ -1955,12 +1970,17 @@ int fixup_user_fault(struct task_struct *tsk, struct mm_struct *mm,
unsigned long address, unsigned int fault_flags)
{
struct vm_area_struct *vma;
+ vm_flags_t vm_flags;
int ret;
vma = find_extend_vma(mm, address);
if (!vma || address < vma->vm_start)
return -EFAULT;
+ vm_flags = (fault_flags & FAULT_FLAG_WRITE) ? VM_WRITE : VM_READ;
+ if (!(vm_flags & vma->vm_flags))
+ return -EFAULT;
+
ret = handle_mm_fault(mm, vma, address, fault_flags);
if (ret & VM_FAULT_ERROR) {
if (ret & VM_FAULT_OOM)
diff --git a/mm/mremap.c b/mm/mremap.c
index 0843feb66f3d..05f1180e9f21 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -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;
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index ef413492a149..a4317da60532 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -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;
diff --git a/mm/percpu.c b/mm/percpu.c
index 63e24fb4387b..2ddf9a990dbd 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -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;
}
diff --git a/mm/slab.c b/mm/slab.c
index 388cb1ae6fbc..19d92181ce24 100644
--- 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;
}
diff --git a/mm/slab.h b/mm/slab.h
index 3045316b7c9d..6bd4c353704f 100644
--- 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;
diff --git a/mm/slab_common.c b/mm/slab_common.c
index f3cfccf76dda..102cc6fca3d3 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -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:
diff --git a/mm/slub.c b/mm/slub.c
index 5e234f1f8853..2b1ce697fc4b 100644
--- 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)
/*
diff --git a/mm/truncate.c b/mm/truncate.c
index e5cc39ab0751..6a78c814bebf 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -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,
diff --git a/mm/util.c b/mm/util.c
index f380af7ea779..d5ea733c5082 100644
--- 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;
diff --git a/mm/vmacache.c b/mm/vmacache.c
index d4224b397c0e..1037a3bab505 100644
--- a/mm/vmacache.c
+++ b/mm/vmacache.c
@@ -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;
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 9b6497eda806..32c661d66a45 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1158,7 +1158,7 @@ unsigned long reclaim_clean_pages_from_list(struct zone *zone,
TTU_UNMAP|TTU_IGNORE_ACCESS,
&dummy1, &dummy2, &dummy3, &dummy4, &dummy5, true);
list_splice(&clean_pages, page_list);
- __mod_zone_page_state(zone, NR_ISOLATED_FILE, -ret);
+ mod_zone_page_state(zone, NR_ISOLATED_FILE, -ret);
return ret;
}
@@ -1916,6 +1916,24 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc,
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.
*/
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 175273f38cb1..44ebd5c2cd4a 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -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;
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 6f142f03716d..019efb79708f 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -524,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,
@@ -559,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);
@@ -608,10 +612,7 @@ static int vlan_dev_init(struct net_device *dev)
SET_NETDEV_DEVTYPE(dev, &vlan_type);
- if (is_vlan_dev(real_dev))
- subclass = 1;
-
- 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)
@@ -783,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)
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index b3bd4ec3fd94..f04224c32005 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -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)
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c
index b25fd64d727b..aa5d4946d0d7 100644
--- a/net/batman-adv/distributed-arp-table.c
+++ b/net/batman-adv/distributed-arp-table.c
@@ -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;
}
diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c
index bcc4bea632fa..f14e54a05691 100644
--- a/net/batman-adv/fragmentation.c
+++ b/net/batman-adv/fragmentation.c
@@ -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;
}
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index c835e137423b..90cff585b37d 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -42,8 +42,10 @@
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;
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index b851cc580853..fbda6b54baff 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -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 */
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index ffd9dfbd9b0e..6a484514cd3e 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -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);
}
@@ -702,6 +707,47 @@ free_orig_node:
}
/**
+ * 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
* @orig_node: orig node which is to be checked
@@ -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;
}
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index d958e2dca52f..521fd4f3985e 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -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;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 49774912cb01..15010a230b6d 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -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;
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 80e1b0f60a30..2acf7fa1fec6 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -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))
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index e74b6d530cb6..e8844d975b32 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -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,
};
diff --git a/net/can/gw.c b/net/can/gw.c
index ac31891967da..050a2110d43f 100644
--- a/net/can/gw.c
+++ b/net/can/gw.c
@@ -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))
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c
index dac7f9b98687..1948d592aa54 100644
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -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.
diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c
index e632b5a52f5b..c547e46084d3 100644
--- a/net/ceph/osdmap.c
+++ b/net/ceph/osdmap.c
@@ -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;
diff --git a/net/core/dev.c b/net/core/dev.c
index 14dac0654f28..9abc503b19b7 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2284,7 +2284,7 @@ EXPORT_SYMBOL(skb_checksum_help);
__be16 skb_network_protocol(struct sk_buff *skb, int *depth)
{
__be16 type = skb->protocol;
- int vlan_depth = ETH_HLEN;
+ int vlan_depth = skb->mac_len;
/* Tunnel gso handlers can set protocol to ethernet. */
if (type == htons(ETH_P_TEB)) {
@@ -2418,7 +2418,7 @@ EXPORT_SYMBOL(netdev_rx_csum_fault);
* 2. No high memory really exists on this machine.
*/
-static int illegal_highdma(const struct net_device *dev, struct sk_buff *skb)
+static int illegal_highdma(struct net_device *dev, struct sk_buff *skb)
{
#ifdef CONFIG_HIGHMEM
int i;
@@ -2493,38 +2493,36 @@ static int dev_gso_segment(struct sk_buff *skb, netdev_features_t features)
}
static netdev_features_t harmonize_features(struct sk_buff *skb,
- const struct net_device *dev,
- netdev_features_t features)
+ netdev_features_t features)
{
int tmp;
if (skb->ip_summed != CHECKSUM_NONE &&
!can_checksum_protocol(features, skb_network_protocol(skb, &tmp))) {
features &= ~NETIF_F_ALL_CSUM;
- } else if (illegal_highdma(dev, skb)) {
+ } else if (illegal_highdma(skb->dev, skb)) {
features &= ~NETIF_F_SG;
}
return features;
}
-netdev_features_t netif_skb_dev_features(struct sk_buff *skb,
- const struct net_device *dev)
+netdev_features_t netif_skb_features(struct sk_buff *skb)
{
__be16 protocol = skb->protocol;
- netdev_features_t features = dev->features;
+ netdev_features_t features = skb->dev->features;
- if (skb_shinfo(skb)->gso_segs > dev->gso_max_segs)
+ if (skb_shinfo(skb)->gso_segs > skb->dev->gso_max_segs)
features &= ~NETIF_F_GSO_MASK;
if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD)) {
struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
protocol = veh->h_vlan_encapsulated_proto;
} else if (!vlan_tx_tag_present(skb)) {
- return harmonize_features(skb, dev, features);
+ return harmonize_features(skb, features);
}
- features &= (dev->vlan_features | NETIF_F_HW_VLAN_CTAG_TX |
+ features &= (skb->dev->vlan_features | NETIF_F_HW_VLAN_CTAG_TX |
NETIF_F_HW_VLAN_STAG_TX);
if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD))
@@ -2532,9 +2530,9 @@ netdev_features_t netif_skb_dev_features(struct sk_buff *skb,
NETIF_F_GEN_CSUM | NETIF_F_HW_VLAN_CTAG_TX |
NETIF_F_HW_VLAN_STAG_TX;
- return harmonize_features(skb, dev, features);
+ return harmonize_features(skb, features);
}
-EXPORT_SYMBOL(netif_skb_dev_features);
+EXPORT_SYMBOL(netif_skb_features);
int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
struct netdev_queue *txq)
@@ -3953,6 +3951,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
}
NAPI_GRO_CB(skb)->count = 1;
NAPI_GRO_CB(skb)->age = jiffies;
+ NAPI_GRO_CB(skb)->last = skb;
skb_shinfo(skb)->gso_size = skb_gro_len(skb);
skb->next = napi->gro_list;
napi->gro_list = skb;
@@ -4543,6 +4542,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
* @iter: list_head ** of the current position
@@ -4624,6 +4649,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
* variant
@@ -5073,6 +5124,30 @@ void *netdev_lower_dev_get_private(struct net_device *dev,
}
EXPORT_SYMBOL(netdev_lower_dev_get_private);
+
+int dev_get_nest_level(struct net_device *dev,
+ bool (*type_check)(struct net_device *dev))
+{
+ struct net_device *lower = NULL;
+ struct list_head *iter;
+ int max_nest = -1;
+ int nest;
+
+ ASSERT_RTNL();
+
+ netdev_for_each_lower_dev(dev, lower, iter) {
+ nest = dev_get_nest_level(lower, type_check);
+ if (max_nest < nest)
+ max_nest = nest;
+ }
+
+ if (type_check(dev))
+ max_nest++;
+
+ return max_nest;
+}
+EXPORT_SYMBOL(dev_get_nest_level);
+
static void dev_change_rx_flags(struct net_device *dev, int flags)
{
const struct net_device_ops *ops = dev->netdev_ops;
@@ -5542,7 +5617,7 @@ static int dev_new_index(struct net *net)
/* Delayed registration/unregisteration */
static LIST_HEAD(net_todo_list);
-static DECLARE_WAIT_QUEUE_HEAD(netdev_unregistering_wq);
+DECLARE_WAIT_QUEUE_HEAD(netdev_unregistering_wq);
static void net_set_todo(struct net_device *dev)
{
diff --git a/net/core/dst.c b/net/core/dst.c
index ca4231ec7347..80d6286c8b62 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -142,12 +142,12 @@ loop:
mutex_unlock(&dst_gc_mutex);
}
-int dst_discard(struct sk_buff *skb)
+int dst_discard_sk(struct sock *sk, struct sk_buff *skb)
{
kfree_skb(skb);
return 0;
}
-EXPORT_SYMBOL(dst_discard);
+EXPORT_SYMBOL(dst_discard_sk);
const u32 dst_default_metrics[RTAX_MAX + 1] = {
/* This initializer is needed to force linker to place this variable
@@ -184,7 +184,7 @@ void *dst_alloc(struct dst_ops *ops, struct net_device *dev,
dst->xfrm = NULL;
#endif
dst->input = dst_discard;
- dst->output = dst_discard;
+ dst->output = dst_discard_sk;
dst->error = 0;
dst->obsolete = initial_obsolete;
dst->header_len = 0;
@@ -209,8 +209,10 @@ static void ___dst_free(struct dst_entry *dst)
/* The first case (dev==NULL) is required, when
protocol module is unloaded.
*/
- if (dst->dev == NULL || !(dst->dev->flags&IFF_UP))
- dst->input = dst->output = dst_discard;
+ if (dst->dev == NULL || !(dst->dev->flags&IFF_UP)) {
+ dst->input = dst_discard;
+ dst->output = dst_discard_sk;
+ }
dst->obsolete = DST_OBSOLETE_DEAD;
}
@@ -361,7 +363,8 @@ static void dst_ifdown(struct dst_entry *dst, struct net_device *dev,
return;
if (!unregister) {
- dst->input = dst->output = dst_discard;
+ dst->input = dst_discard;
+ dst->output = dst_discard_sk;
} else {
dst->dev = dev_net(dst->dev)->loopback_dev;
dev_hold(dst->dev);
diff --git a/net/core/filter.c b/net/core/filter.c
index e08b3822c72a..9d79ca0a6e8e 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -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];
@@ -600,6 +609,9 @@ static u64 __skb_get_nlattr(u64 ctx, u64 A, u64 X, u64 r4, u64 r5)
if (skb_is_nonlinear(skb))
return 0;
+ if (skb->len < sizeof(struct nlattr))
+ return 0;
+
if (A > skb->len - sizeof(struct nlattr))
return 0;
@@ -618,11 +630,14 @@ static u64 __skb_get_nlattr_nest(u64 ctx, u64 A, u64 X, u64 r4, u64 r5)
if (skb_is_nonlinear(skb))
return 0;
+ if (skb->len < sizeof(struct nlattr))
+ return 0;
+
if (A > skb->len - sizeof(struct nlattr))
return 0;
nla = (struct nlattr *) &skb->data[A];
- if (nla->nla_len > A - skb->len)
+ if (nla->nla_len > skb->len - A)
return 0;
nla = nla_find_nested(nla, X);
@@ -637,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)
{
@@ -1737,7 +1745,6 @@ void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to)
[BPF_S_ANC_RXHASH] = BPF_LD|BPF_B|BPF_ABS,
[BPF_S_ANC_CPU] = BPF_LD|BPF_B|BPF_ABS,
[BPF_S_ANC_ALU_XOR_X] = BPF_LD|BPF_B|BPF_ABS,
- [BPF_S_ANC_SECCOMP_LD_W] = BPF_LD|BPF_B|BPF_ABS,
[BPF_S_ANC_VLAN_TAG] = BPF_LD|BPF_B|BPF_ABS,
[BPF_S_ANC_VLAN_TAG_PRESENT] = BPF_LD|BPF_B|BPF_ABS,
[BPF_S_ANC_PAY_OFFSET] = BPF_LD|BPF_B|BPF_ABS,
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 8f8a96ef9f3f..32d872eec7f5 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -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));
}
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 81d3a9a08453..7c8ffd974961 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -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);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index d4ff41739b0f..2d8d8fcfa060 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -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) {
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 1b62343f5837..8383b2bddeb9 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -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;
diff --git a/net/core/sock.c b/net/core/sock.c
index b4fff008136f..664ee4295b6f 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -145,6 +145,55 @@
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)
{
diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c
index d7af18859322..a4216a4c9572 100644
--- a/net/core/sock_diag.c
+++ b/net/core/sock_diag.c
@@ -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;
}
diff --git a/net/core/utils.c b/net/core/utils.c
index 2f737bf90b3f..eed34338736c 100644
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -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;
}
diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c
index 553644402670..f8b98d89c285 100644
--- a/net/dcb/dcbnl.c
+++ b/net/dcb/dcbnl.c
@@ -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,
diff --git a/net/dccp/output.c b/net/dccp/output.c
index 8876078859da..0248e8a3460c 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -138,7 +138,7 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
- err = icsk->icsk_af_ops->queue_xmit(skb, &inet->cork.fl);
+ err = icsk->icsk_af_ops->queue_xmit(sk, skb, &inet->cork.fl);
return net_xmit_eval(err);
}
return -ENOBUFS;
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index a603823a3e27..3b726f31c64c 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -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))
diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c
index 57dc159245ec..d332aefb0846 100644
--- a/net/decnet/dn_fib.c
+++ b/net/decnet/dn_fib.c
@@ -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))
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index ce0cbbfe0f43..daccc4a36d80 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -752,7 +752,7 @@ static int dn_to_neigh_output(struct sk_buff *skb)
return n->output(n, skb);
}
-static int dn_output(struct sk_buff *skb)
+static int dn_output(struct sock *sk, struct sk_buff *skb)
{
struct dst_entry *dst = skb_dst(skb);
struct dn_route *rt = (struct dn_route *)dst;
@@ -838,6 +838,18 @@ drop:
* Used to catch bugs. This should never normally get
* called.
*/
+static int dn_rt_bug_sk(struct sock *sk, struct sk_buff *skb)
+{
+ struct dn_skb_cb *cb = DN_SKB_CB(skb);
+
+ net_dbg_ratelimited("dn_rt_bug: skb from:%04x to:%04x\n",
+ le16_to_cpu(cb->src), le16_to_cpu(cb->dst));
+
+ kfree_skb(skb);
+
+ return NET_RX_DROP;
+}
+
static int dn_rt_bug(struct sk_buff *skb)
{
struct dn_skb_cb *cb = DN_SKB_CB(skb);
@@ -1463,7 +1475,7 @@ make_route:
rt->n = neigh;
rt->dst.lastuse = jiffies;
- rt->dst.output = dn_rt_bug;
+ rt->dst.output = dn_rt_bug_sk;
switch (res.type) {
case RTN_UNICAST:
rt->dst.input = dn_forward;
diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c
index e83015cecfa7..e4d9560a910b 100644
--- a/net/decnet/netfilter/dn_rtmsg.c
+++ b/net/decnet/netfilter/dn_rtmsg.c
@@ -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 */
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 0eb5d5e76dfb..5db37cef50a9 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -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;
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 8c54870db792..6d6dd345bc4d 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -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
*/
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 1a629f870274..255aa9946fe7 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -250,7 +250,7 @@ static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
bool dev_match;
fl4.flowi4_oif = 0;
- fl4.flowi4_iif = oif;
+ fl4.flowi4_iif = oif ? : LOOPBACK_IFINDEX;
fl4.daddr = src;
fl4.saddr = dst;
fl4.flowi4_tos = tos;
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index b53f0bf84dca..b10cd43a4722 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -631,6 +631,7 @@ static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi,
.daddr = nh->nh_gw,
.flowi4_scope = cfg->fc_scope + 1,
.flowi4_oif = nh->nh_oif,
+ .flowi4_iif = LOOPBACK_IFINDEX,
};
/* It is not necessary, but requires a bit of thinking */
@@ -820,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;
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 0d1e2cb877ec..a56b8e6e866a 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -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);
diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c
index be8abe73bb9f..6f111e48e11c 100644
--- a/net/ipv4/ip_forward.c
+++ b/net/ipv4/ip_forward.c
@@ -42,12 +42,12 @@
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);
}
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index c10a3ce5cbff..ed32313e307c 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -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;
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 1a0755fea491..a52f50187b54 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -101,17 +101,17 @@ int __ip_local_out(struct sk_buff *skb)
skb_dst(skb)->dev, dst_output);
}
-int ip_local_out(struct sk_buff *skb)
+int ip_local_out_sk(struct sock *sk, struct sk_buff *skb)
{
int err;
err = __ip_local_out(skb);
if (likely(err == 1))
- err = dst_output(skb);
+ err = dst_output_sk(sk, skb);
return err;
}
-EXPORT_SYMBOL_GPL(ip_local_out);
+EXPORT_SYMBOL_GPL(ip_local_out_sk);
static inline int ip_select_ttl(struct inet_sock *inet, struct dst_entry *dst)
{
@@ -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,15 +262,17 @@ 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 sk_buff *skb)
+int ip_mc_output(struct sock *sk, struct sk_buff *skb)
{
- struct sock *sk = skb->sk;
struct rtable *rt = skb_rtable(skb);
struct net_device *dev = rt->dst.dev;
@@ -287,7 +331,7 @@ int ip_mc_output(struct sk_buff *skb)
!(IPCB(skb)->flags & IPSKB_REROUTED));
}
-int ip_output(struct sk_buff *skb)
+int ip_output(struct sock *sk, struct sk_buff *skb)
{
struct net_device *dev = skb_dst(skb)->dev;
@@ -315,9 +359,9 @@ static void ip_copy_addrs(struct iphdr *iph, const struct flowi4 *fl4)
sizeof(fl4->saddr) + sizeof(fl4->daddr));
}
-int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl)
+/* Note: skb->sk can be different from sk, in case of tunnels */
+int ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl)
{
- struct sock *sk = skb->sk;
struct inet_sock *inet = inet_sk(sk);
struct ip_options_rcu *inet_opt;
struct flowi4 *fl4;
@@ -389,6 +433,7 @@ packet_routed:
ip_select_ident_more(skb, &rt->dst, sk,
(skb_shinfo(skb)->gso_segs ?: 1) - 1);
+ /* TODO : should we use skb->sk here instead of sk ? */
skb->priority = sk->sk_priority;
skb->mark = sk->sk_mark;
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index e77381d1df9a..2acc2337d38b 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -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) {
@@ -670,7 +673,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
return;
}
- err = iptunnel_xmit(rt, skb, fl4.saddr, fl4.daddr, protocol,
+ err = iptunnel_xmit(skb->sk, rt, skb, fl4.saddr, fl4.daddr, protocol,
tos, ttl, df, !net_eq(tunnel->net, dev_net(dev)));
iptunnel_xmit_stats(err, &dev->stats, dev->tstats);
@@ -722,19 +725,18 @@ static void ip_tunnel_update(struct ip_tunnel_net *itn,
int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd)
{
int err = 0;
- struct ip_tunnel *t;
- struct net *net = dev_net(dev);
- struct ip_tunnel *tunnel = netdev_priv(dev);
- struct ip_tunnel_net *itn = net_generic(net, tunnel->ip_tnl_net_id);
+ struct ip_tunnel *t = netdev_priv(dev);
+ struct net *net = t->net;
+ struct ip_tunnel_net *itn = net_generic(net, t->ip_tnl_net_id);
BUG_ON(!itn->fb_tunnel_dev);
switch (cmd) {
case SIOCGETTUNNEL:
- t = NULL;
- if (dev == itn->fb_tunnel_dev)
+ if (dev == itn->fb_tunnel_dev) {
t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type);
- if (t == NULL)
- t = netdev_priv(dev);
+ if (t == NULL)
+ t = netdev_priv(dev);
+ }
memcpy(p, &t->parms, sizeof(*p));
break;
@@ -881,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();
diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
index e0c2b1d2ea4e..bcf206c79005 100644
--- a/net/ipv4/ip_tunnel_core.c
+++ b/net/ipv4/ip_tunnel_core.c
@@ -46,7 +46,7 @@
#include <net/netns/generic.h>
#include <net/rtnetlink.h>
-int iptunnel_xmit(struct rtable *rt, struct sk_buff *skb,
+int iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
__be32 src, __be32 dst, __u8 proto,
__u8 tos, __u8 ttl, __be16 df, bool xnet)
{
@@ -76,7 +76,7 @@ int iptunnel_xmit(struct rtable *rt, struct sk_buff *skb,
iph->ttl = ttl;
__ip_select_ident(iph, &rt->dst, (skb_shinfo(skb)->gso_segs ?: 1) - 1);
- err = ip_local_out(skb);
+ err = ip_local_out_sk(sk, skb);
if (unlikely(net_xmit_eval(err)))
pkt_len = 0;
return pkt_len;
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index afcee51b90ed..13ef00f1e17b 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -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;
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 28863570dd60..d84dc8d4c916 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -455,7 +455,7 @@ static netdev_tx_t reg_vif_xmit(struct sk_buff *skb, struct net_device *dev)
struct mr_table *mrt;
struct flowi4 fl4 = {
.flowi4_oif = dev->ifindex,
- .flowi4_iif = skb->skb_iif,
+ .flowi4_iif = skb->skb_iif ? : LOOPBACK_IFINDEX,
.flowi4_mark = skb->mark,
};
int err;
diff --git a/net/ipv4/netfilter/ipt_rpfilter.c b/net/ipv4/netfilter/ipt_rpfilter.c
index c49dcd0284a0..4bfaedf9b34e 100644
--- a/net/ipv4/netfilter/ipt_rpfilter.c
+++ b/net/ipv4/netfilter/ipt_rpfilter.c
@@ -89,11 +89,8 @@ static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par)
if (ipv4_is_multicast(iph->daddr)) {
if (ipv4_is_zeronet(iph->saddr))
return ipv4_is_local_multicast(iph->daddr) ^ invert;
- flow.flowi4_iif = 0;
- } else {
- flow.flowi4_iif = LOOPBACK_IFINDEX;
}
-
+ flow.flowi4_iif = LOOPBACK_IFINDEX;
flow.daddr = iph->saddr;
flow.saddr = rpfilter_get_saddr(iph->daddr);
flow.flowi4_oif = 0;
diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c
index 12e13bd82b5b..f40f321b41fc 100644
--- a/net/ipv4/netfilter/nf_defrag_ipv4.c
+++ b/net/ipv4/netfilter/nf_defrag_ipv4.c
@@ -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;
}
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index f4b19e5dde54..044a0ddf6a79 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -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));
}
@@ -252,26 +252,33 @@ int ping_init_sock(struct sock *sk)
{
struct net *net = sock_net(sk);
kgid_t group = current_egid();
- struct group_info *group_info = get_current_groups();
- int i, j, count = group_info->ngroups;
+ struct group_info *group_info;
+ int i, j, count;
kgid_t low, high;
+ int ret = 0;
inet_get_ping_group_range_net(net, &low, &high);
if (gid_lte(low, group) && gid_lte(group, high))
return 0;
+ group_info = get_current_groups();
+ count = group_info->ngroups;
for (i = 0; i < group_info->nblocks; i++) {
int cp_count = min_t(int, NGROUPS_PER_BLOCK, count);
for (j = 0; j < cp_count; j++) {
kgid_t gid = group_info->blocks[i][j];
if (gid_lte(low, gid) && gid_lte(gid, high))
- return 0;
+ goto out_release_group;
}
count -= cp_count;
}
- return -EACCES;
+ ret = -EACCES;
+
+out_release_group:
+ put_group_info(group_info);
+ return ret;
}
EXPORT_SYMBOL_GPL(ping_init_sock);
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 34d094cadb11..5e676be3daeb 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1129,7 +1129,7 @@ static void ipv4_link_failure(struct sk_buff *skb)
dst_set_expires(&rt->dst, 0);
}
-static int ip_rt_bug(struct sk_buff *skb)
+static int ip_rt_bug(struct sock *sk, struct sk_buff *skb)
{
pr_debug("%s: %pI4 -> %pI4, %s\n",
__func__, &ip_hdr(skb)->saddr, &ip_hdr(skb)->daddr,
@@ -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));
@@ -1700,8 +1700,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
if (res.type == RTN_LOCAL) {
err = fib_validate_source(skb, saddr, daddr, tos,
- LOOPBACK_IFINDEX,
- dev, in_dev, &itag);
+ 0, dev, in_dev, &itag);
if (err < 0)
goto martian_source_keep_err;
goto local_input;
@@ -2218,7 +2217,7 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or
new->__use = 1;
new->input = dst_discard;
- new->output = dst_discard;
+ new->output = dst_discard_sk;
new->dev = ort->dst.dev;
if (new->dev)
@@ -2357,7 +2356,7 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src,
}
} else
#endif
- if (nla_put_u32(skb, RTA_IIF, rt->rt_iif))
+ if (nla_put_u32(skb, RTA_IIF, skb->dev->ifindex))
goto nla_put_failure;
}
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 44eba052b43d..5cde8f263d40 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -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;
diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c
index 8bf224516ba2..b4f1b29b08bd 100644
--- a/net/ipv4/tcp_cubic.c
+++ b/net/ipv4/tcp_cubic.c
@@ -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 */
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 699fb102e971..12d6016bdd9a 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -981,7 +981,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
TCP_ADD_STATS(sock_net(sk), TCP_MIB_OUTSEGS,
tcp_skb_pcount(skb));
- err = icsk->icsk_af_ops->queue_xmit(skb, &inet->cork.fl);
+ err = icsk->icsk_af_ops->queue_xmit(sk, skb, &inet->cork.fl);
if (likely(err <= 0))
return err;
@@ -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");
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index baa0f63731fd..186a8ecf92fa 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -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)
{
-#ifdef CONFIG_NETFILTER
- if (!skb_dst(skb)->xfrm) {
- IPCB(skb)->flags |= IPSKB_REROUTED;
- return dst_output(skb);
- }
+ memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
+ skb->protocol = htons(ETH_P_IP);
+#ifdef CONFIG_NETFILTER
IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
#endif
- skb->protocol = htons(ETH_P_IP);
return xfrm_output(skb);
}
-int xfrm4_output(struct sk_buff *skb)
+static int __xfrm4_output(struct sk_buff *skb)
{
- struct dst_entry *dst = skb_dst(skb);
- struct xfrm_state *x = dst->xfrm;
+ struct xfrm_state *x = skb_dst(skb)->xfrm;
+
+#ifdef CONFIG_NETFILTER
+ if (!x) {
+ IPCB(skb)->flags |= IPSKB_REROUTED;
+ return dst_output(skb);
+ }
+#endif
+ return x->outer_mode->afinfo->output_finish(skb);
+}
+
+int xfrm4_output(struct sock *sk, struct sk_buff *skb)
+{
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));
}
diff --git a/net/ipv4/xfrm4_protocol.c b/net/ipv4/xfrm4_protocol.c
index 7f7b243e8139..a2ce0101eaac 100644
--- a/net/ipv4/xfrm4_protocol.c
+++ b/net/ipv4/xfrm4_protocol.c
@@ -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);
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index c9138189415a..d4ade34ab375 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -224,9 +224,8 @@ static struct dst_entry *inet6_csk_route_socket(struct sock *sk,
return dst;
}
-int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl_unused)
+int inet6_csk_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl_unused)
{
- struct sock *sk = skb->sk;
struct ipv6_pinfo *np = inet6_sk(sk);
struct flowi6 fl6;
struct dst_entry *dst;
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 34e0ded5c14b..87891f5f57b5 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -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)
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index c98338b81d30..9d921462b57f 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -1559,6 +1559,15 @@ static int ip6gre_changelink(struct net_device *dev, struct nlattr *tb[],
return 0;
}
+static void ip6gre_dellink(struct net_device *dev, struct list_head *head)
+{
+ struct net *net = dev_net(dev);
+ struct ip6gre_net *ign = net_generic(net, ip6gre_net_id);
+
+ if (dev != ign->fb_tunnel_dev)
+ unregister_netdevice_queue(dev, head);
+}
+
static size_t ip6gre_get_size(const struct net_device *dev)
{
return
@@ -1636,6 +1645,7 @@ static struct rtnl_link_ops ip6gre_link_ops __read_mostly = {
.validate = ip6gre_tunnel_validate,
.newlink = ip6gre_newlink,
.changelink = ip6gre_changelink,
+ .dellink = ip6gre_dellink,
.get_size = ip6gre_get_size,
.fill_info = ip6gre_fill_info,
};
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
index 59f95affceb0..b2f091566f88 100644
--- a/net/ipv6/ip6_offload.c
+++ b/net/ipv6/ip6_offload.c
@@ -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();
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 3284d61577c0..fbf11562b54c 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -132,7 +132,7 @@ static int ip6_finish_output(struct sk_buff *skb)
return ip6_finish_output2(skb);
}
-int ip6_output(struct sk_buff *skb)
+int ip6_output(struct sock *sk, struct sk_buff *skb)
{
struct net_device *dev = skb_dst(skb)->dev;
struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb));
@@ -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;
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index e1df691d78be..f6a66bb4114d 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1340,8 +1340,8 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
int err = 0;
struct ip6_tnl_parm p;
struct __ip6_tnl_parm p1;
- struct ip6_tnl *t = NULL;
- struct net *net = dev_net(dev);
+ struct ip6_tnl *t = netdev_priv(dev);
+ struct net *net = t->net;
struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
switch (cmd) {
@@ -1353,11 +1353,11 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
}
ip6_tnl_parm_from_user(&p1, &p);
t = ip6_tnl_locate(net, &p1, 0);
+ if (t == NULL)
+ t = netdev_priv(dev);
} else {
memset(&p, 0, sizeof(p));
}
- if (t == NULL)
- t = netdev_priv(dev);
ip6_tnl_parm_to_user(&p, &t->parms);
if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof (p))) {
err = -EFAULT;
@@ -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]);
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
index b7c0f827140b..6cc9f9371cc5 100644
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@ -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;
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 8737400af0a0..8250474ab7dc 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -700,7 +700,7 @@ static netdev_tx_t reg_vif_xmit(struct sk_buff *skb,
struct mr6_table *mrt;
struct flowi6 fl6 = {
.flowi6_oif = dev->ifindex,
- .flowi6_iif = skb->skb_iif,
+ .flowi6_iif = skb->skb_iif ? : LOOPBACK_IFINDEX,
.flowi6_mark = skb->mark,
};
int err;
@@ -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,
};
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 09a22f4f36c9..ca8d4ea48a5d 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -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:
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
index 95f3f1da0d7f..d38e6a8d8b9f 100644
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -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. */
diff --git a/net/ipv6/netfilter/ip6t_rpfilter.c b/net/ipv6/netfilter/ip6t_rpfilter.c
index e0983f3648a6..790e0c6b19e1 100644
--- a/net/ipv6/netfilter/ip6t_rpfilter.c
+++ b/net/ipv6/netfilter/ip6t_rpfilter.c
@@ -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,
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 5015c50a5ba7..6ebdb7b6744c 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -84,9 +84,9 @@ static void ip6_dst_ifdown(struct dst_entry *,
static int ip6_dst_gc(struct dst_ops *ops);
static int ip6_pkt_discard(struct sk_buff *skb);
-static int ip6_pkt_discard_out(struct sk_buff *skb);
+static int ip6_pkt_discard_out(struct sock *sk, struct sk_buff *skb);
static int ip6_pkt_prohibit(struct sk_buff *skb);
-static int ip6_pkt_prohibit_out(struct sk_buff *skb);
+static int ip6_pkt_prohibit_out(struct sock *sk, struct sk_buff *skb);
static void ip6_link_failure(struct sk_buff *skb);
static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
struct sk_buff *skb, u32 mtu);
@@ -290,7 +290,7 @@ static const struct rt6_info ip6_blk_hole_entry_template = {
.obsolete = DST_OBSOLETE_FORCE_CHK,
.error = -EINVAL,
.input = dst_discard,
- .output = dst_discard,
+ .output = dst_discard_sk,
},
.rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
.rt6i_protocol = RTPROT_KERNEL,
@@ -1058,7 +1058,7 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori
new->__use = 1;
new->input = dst_discard;
- new->output = dst_discard;
+ new->output = dst_discard_sk;
if (dst_metrics_read_only(&ort->dst))
new->_metrics = ort->dst._metrics;
@@ -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;
@@ -1338,7 +1340,7 @@ static unsigned int ip6_mtu(const struct dst_entry *dst)
unsigned int mtu = dst_metric_raw(dst, RTAX_MTU);
if (mtu)
- return mtu;
+ goto out;
mtu = IPV6_MIN_MTU;
@@ -1348,7 +1350,8 @@ static unsigned int ip6_mtu(const struct dst_entry *dst)
mtu = idev->cnf.mtu6;
rcu_read_unlock();
- return mtu;
+out:
+ return min_t(unsigned int, mtu, IP6_MAX_MTU);
}
static struct dst_entry *icmp6_dst_gc_list;
@@ -1576,7 +1579,7 @@ int ip6_route_add(struct fib6_config *cfg)
switch (cfg->fc_type) {
case RTN_BLACKHOLE:
rt->dst.error = -EINVAL;
- rt->dst.output = dst_discard;
+ rt->dst.output = dst_discard_sk;
rt->dst.input = dst_discard;
break;
case RTN_PROHIBIT:
@@ -2128,7 +2131,7 @@ static int ip6_pkt_discard(struct sk_buff *skb)
return ip6_pkt_drop(skb, ICMPV6_NOROUTE, IPSTATS_MIB_INNOROUTES);
}
-static int ip6_pkt_discard_out(struct sk_buff *skb)
+static int ip6_pkt_discard_out(struct sock *sk, struct sk_buff *skb)
{
skb->dev = skb_dst(skb)->dev;
return ip6_pkt_drop(skb, ICMPV6_NOROUTE, IPSTATS_MIB_OUTNOROUTES);
@@ -2139,7 +2142,7 @@ static int ip6_pkt_prohibit(struct sk_buff *skb)
return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_INNOROUTES);
}
-static int ip6_pkt_prohibit_out(struct sk_buff *skb)
+static int ip6_pkt_prohibit_out(struct sock *sk, struct sk_buff *skb)
{
skb->dev = skb_dst(skb)->dev;
return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES);
@@ -2231,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;
@@ -2706,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;
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 1693c8d885f0..e5a453ca302e 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -974,8 +974,9 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
goto out;
}
- err = iptunnel_xmit(rt, skb, fl4.saddr, fl4.daddr, IPPROTO_IPV6, tos,
- ttl, df, !net_eq(tunnel->net, dev_net(dev)));
+ err = iptunnel_xmit(skb->sk, rt, skb, fl4.saddr, fl4.daddr,
+ IPPROTO_IPV6, tos, ttl, df,
+ !net_eq(tunnel->net, dev_net(dev)));
iptunnel_xmit_stats(err, &dev->stats, dev->tstats);
return NETDEV_TX_OK;
@@ -1126,8 +1127,8 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
int err = 0;
struct ip_tunnel_parm p;
struct ip_tunnel_prl prl;
- struct ip_tunnel *t;
- struct net *net = dev_net(dev);
+ struct ip_tunnel *t = netdev_priv(dev);
+ struct net *net = t->net;
struct sit_net *sitn = net_generic(net, sit_net_id);
#ifdef CONFIG_IPV6_SIT_6RD
struct ip_tunnel_6rd ip6rd;
@@ -1138,16 +1139,15 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
#ifdef CONFIG_IPV6_SIT_6RD
case SIOCGET6RD:
#endif
- t = NULL;
if (dev == sitn->fb_tunnel_dev) {
if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) {
err = -EFAULT;
break;
}
t = ipip6_tunnel_locate(net, &p, 0);
+ if (t == NULL)
+ t = netdev_priv(dev);
}
- if (t == NULL)
- t = netdev_priv(dev);
err = -EFAULT;
if (cmd == SIOCGETTUNNEL) {
@@ -1243,9 +1243,6 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
err = -EINVAL;
if (dev == sitn->fb_tunnel_dev)
goto done;
- err = -ENOENT;
- if (!(t = netdev_priv(dev)))
- goto done;
err = ipip6_tunnel_get_prl(t, ifr->ifr_ifru.ifru_data);
break;
@@ -1261,9 +1258,6 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
err = -EFAULT;
if (copy_from_user(&prl, ifr->ifr_ifru.ifru_data, sizeof(prl)))
goto done;
- err = -ENOENT;
- if (!(t = netdev_priv(dev)))
- goto done;
switch (cmd) {
case SIOCDELPRL:
@@ -1291,8 +1285,6 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
sizeof(ip6rd)))
goto done;
- t = netdev_priv(dev);
-
if (cmd != SIOCDEL6RD) {
err = ipip6_tunnel_update_6rd(t, &ip6rd);
if (err < 0)
diff --git a/net/ipv6/tcpv6_offload.c b/net/ipv6/tcpv6_offload.c
index 0d78132ff18a..8517d3cd1aed 100644
--- a/net/ipv6/tcpv6_offload.c
+++ b/net/ipv6/tcpv6_offload.c
@@ -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:
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
index 6cd625e37706..b930d080c66f 100644
--- a/net/ipv6/xfrm6_output.c
+++ b/net/ipv6/xfrm6_output.c
@@ -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
@@ -163,8 +166,9 @@ static int __xfrm6_output(struct sk_buff *skb)
return x->outer_mode->afinfo->output_finish(skb);
}
-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));
}
diff --git a/net/ipv6/xfrm6_protocol.c b/net/ipv6/xfrm6_protocol.c
index 6ab989c486f7..54d13f8dbbae 100644
--- a/net/ipv6/xfrm6_protocol.c
+++ b/net/ipv6/xfrm6_protocol.c
@@ -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);
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
index 01e77b0ae075..8c9d7302c846 100644
--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -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;
}
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index 47f7a5490555..a4e37d7158dc 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -1131,10 +1131,10 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb,
skb->local_df = 1;
#if IS_ENABLED(CONFIG_IPV6)
if (tunnel->sock->sk_family == PF_INET6 && !tunnel->v4mapped)
- error = inet6_csk_xmit(skb, NULL);
+ error = inet6_csk_xmit(tunnel->sock, skb, NULL);
else
#endif
- error = ip_queue_xmit(skb, fl);
+ error = ip_queue_xmit(tunnel->sock, skb, fl);
/* Update stats */
if (error >= 0) {
diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c
index 0b44d855269c..3397fe6897c0 100644
--- a/net/l2tp/l2tp_ip.c
+++ b/net/l2tp/l2tp_ip.c
@@ -487,7 +487,7 @@ static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m
xmit:
/* Queue the packet to IP for output */
- rc = ip_queue_xmit(skb, &inet->cork.fl);
+ rc = ip_queue_xmit(sk, skb, &inet->cork.fl);
rcu_read_unlock();
error:
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index bd1fd8ea5105..75b5dd2c9267 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -249,7 +249,7 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
if (!local->use_chanctx) {
local->_oper_chandef = *chandef;
- ieee80211_hw_config(local, 0);
+ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
} else {
err = drv_add_chanctx(local, ctx);
if (err) {
@@ -286,7 +286,7 @@ static void ieee80211_free_chanctx(struct ieee80211_local *local,
check_single_channel = true;
local->hw.conf.radar_enabled = false;
- ieee80211_hw_config(local, 0);
+ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
} else {
drv_remove_chanctx(local, ctx);
}
@@ -492,6 +492,13 @@ void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
rx_chains_static = max(rx_chains_static, needed_static);
rx_chains_dynamic = max(rx_chains_dynamic, needed_dynamic);
}
+
+ /* Disable SMPS for the monitor interface */
+ sdata = rcu_dereference(local->monitor_sdata);
+ if (sdata &&
+ rcu_access_pointer(sdata->vif.chanctx_conf) == &chanctx->conf)
+ rx_chains_dynamic = rx_chains_static = local->rx_chains;
+
rcu_read_unlock();
if (!local->use_chanctx) {
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 222c28b75315..f169b6ee94ee 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -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;
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index b055f6a55c68..4c1bf61bc778 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -148,6 +148,8 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
if (!rcu_access_pointer(sdata->vif.chanctx_conf))
continue;
+ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+ continue;
power = min(power, sdata->vif.bss_conf.txpower);
}
rcu_read_unlock();
@@ -199,7 +201,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
{
struct ieee80211_local *local = sdata->local;
- if (!changed)
+ if (!changed || sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
return;
drv_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index dee50aefd6e8..27600a9808ba 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -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);
}
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index 0c2a29484c07..7a17decd27f9 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -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,13 +354,26 @@ void ieee80211_sw_roc_work(struct work_struct *work)
if (!roc->started) {
struct ieee80211_roc_work *dep;
- /* start this ROC */
+ 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);
@@ -379,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;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 216c45b949e5..2b608b2b70ec 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -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;
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 137a192e64bc..847d92f6bef6 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -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) {
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index e6e574a307c8..60cb7a665976 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -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);
@@ -618,6 +617,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
sta, true, acked);
if ((local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) &&
+ (ieee80211_is_data(hdr->frame_control)) &&
(rates_idx != -1))
sta->last_tx_rate = info->status.rates[rates_idx];
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index a0b0aea76525..cec5b60487a4 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -21,10 +21,10 @@
#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" : ""
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 275c94f995f7..3c365837e910 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -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.
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
index e9e36a256165..9265adfdabfc 100644
--- a/net/mac80211/vht.c
+++ b/net/mac80211/vht.c
@@ -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;
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 6dba48efe01e..75421f2ba8be 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1795,6 +1795,7 @@ int nf_conntrack_init_net(struct net *net)
int cpu;
atomic_set(&net->ct.count, 0);
+ seqcount_init(&net->ct.generation);
net->ct.pcpu_lists = alloc_percpu(struct ct_pcpu);
if (!net->ct.pcpu_lists)
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index ccc46fa5edbc..58579634427d 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -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)
diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c
index 7bd03decd36c..825c3e3f8305 100644
--- a/net/netfilter/nf_conntrack_pptp.c
+++ b/net/netfilter/nf_conntrack_pptp.c
@@ -605,32 +605,14 @@ static struct nf_conntrack_helper pptp __read_mostly = {
.expect_policy = &pptp_exp_policy,
};
-static void nf_conntrack_pptp_net_exit(struct net *net)
-{
- nf_ct_gre_keymap_flush(net);
-}
-
-static struct pernet_operations nf_conntrack_pptp_net_ops = {
- .exit = nf_conntrack_pptp_net_exit,
-};
-
static int __init nf_conntrack_pptp_init(void)
{
- int rv;
-
- rv = nf_conntrack_helper_register(&pptp);
- if (rv < 0)
- return rv;
- rv = register_pernet_subsys(&nf_conntrack_pptp_net_ops);
- if (rv < 0)
- nf_conntrack_helper_unregister(&pptp);
- return rv;
+ return nf_conntrack_helper_register(&pptp);
}
static void __exit nf_conntrack_pptp_fini(void)
{
nf_conntrack_helper_unregister(&pptp);
- unregister_pernet_subsys(&nf_conntrack_pptp_net_ops);
}
module_init(nf_conntrack_pptp_init);
diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c
index 9d9c0dade602..d5665739e3b1 100644
--- a/net/netfilter/nf_conntrack_proto_gre.c
+++ b/net/netfilter/nf_conntrack_proto_gre.c
@@ -66,7 +66,7 @@ static inline struct netns_proto_gre *gre_pernet(struct net *net)
return net_generic(net, proto_gre_net_id);
}
-void nf_ct_gre_keymap_flush(struct net *net)
+static void nf_ct_gre_keymap_flush(struct net *net)
{
struct netns_proto_gre *net_gre = gre_pernet(net);
struct nf_ct_gre_keymap *km, *tmp;
@@ -78,7 +78,6 @@ void nf_ct_gre_keymap_flush(struct net *net)
}
write_unlock_bh(&net_gre->keymap_lock);
}
-EXPORT_SYMBOL(nf_ct_gre_keymap_flush);
static inline int gre_key_cmpfn(const struct nf_ct_gre_keymap *km,
const struct nf_conntrack_tuple *t)
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c
index 90998a6ff8b9..345acfb1720b 100644
--- a/net/netfilter/nf_tables_core.c
+++ b/net/netfilter/nf_tables_core.c
@@ -25,9 +25,8 @@ static void nft_cmp_fast_eval(const struct nft_expr *expr,
struct nft_data data[NFT_REG_MAX + 1])
{
const struct nft_cmp_fast_expr *priv = nft_expr_priv(expr);
- u32 mask;
+ u32 mask = nft_cmp_fast_mask(priv->len);
- mask = ~0U >> (sizeof(priv->data) * BITS_PER_BYTE - priv->len);
if ((data[priv->sreg].data[0] & mask) == priv->data)
return;
data[NFT_REG_VERDICT].verdict = NFT_BREAK;
@@ -67,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,
@@ -118,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.
@@ -132,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;
@@ -157,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;
@@ -184,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);
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index e8138da4c14f..23ef77c60fff 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -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;
}
diff --git a/net/netfilter/nft_cmp.c b/net/netfilter/nft_cmp.c
index 954925db414d..e2b3f51c81f1 100644
--- a/net/netfilter/nft_cmp.c
+++ b/net/netfilter/nft_cmp.c
@@ -128,7 +128,7 @@ static int nft_cmp_fast_init(const struct nft_ctx *ctx,
BUG_ON(err < 0);
desc.len *= BITS_PER_BYTE;
- mask = ~0U >> (sizeof(priv->data) * BITS_PER_BYTE - desc.len);
+ mask = nft_cmp_fast_mask(desc.len);
priv->data = data.data[0] & mask;
priv->len = desc.len;
return 0;
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 894cda0206bb..81dca96d2be6 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1360,7 +1360,72 @@ retry:
return err;
}
-static inline int netlink_capable(const struct socket *sock, unsigned int flag)
+/**
+ * __netlink_ns_capable - General netlink message capability test
+ * @nsp: NETLINK_CB of the socket buffer holding a netlink command from userspace.
+ * @user_ns: The user namespace of the capability to use
+ * @cap: The capability to use
+ *
+ * Test to see if the opener of the socket we received the message
+ * from had when the netlink socket was created and the sender of the
+ * message has has the capability @cap in the user namespace @user_ns.
+ */
+bool __netlink_ns_capable(const struct netlink_skb_parms *nsp,
+ struct user_namespace *user_ns, int cap)
+{
+ return sk_ns_capable(nsp->sk, user_ns, cap);
+}
+EXPORT_SYMBOL(__netlink_ns_capable);
+
+/**
+ * netlink_ns_capable - General netlink message capability test
+ * @skb: socket buffer holding a netlink command from userspace
+ * @user_ns: The user namespace of the capability to use
+ * @cap: The capability to use
+ *
+ * Test to see if the opener of the socket we received the message
+ * from had when the netlink socket was created and the sender of the
+ * message has has the capability @cap in the user namespace @user_ns.
+ */
+bool netlink_ns_capable(const struct sk_buff *skb,
+ struct user_namespace *user_ns, int cap)
+{
+ return __netlink_ns_capable(&NETLINK_CB(skb), user_ns, cap);
+}
+EXPORT_SYMBOL(netlink_ns_capable);
+
+/**
+ * netlink_capable - Netlink global message capability test
+ * @skb: socket buffer holding a netlink command from userspace
+ * @cap: The capability to use
+ *
+ * Test to see if the opener of the socket we received the message
+ * from had when the netlink socket was created and the sender of the
+ * message has has the capability @cap in all user namespaces.
+ */
+bool netlink_capable(const struct sk_buff *skb, int cap)
+{
+ return netlink_ns_capable(skb, &init_user_ns, cap);
+}
+EXPORT_SYMBOL(netlink_capable);
+
+/**
+ * netlink_net_capable - Netlink network namespace message capability test
+ * @skb: socket buffer holding a netlink command from userspace
+ * @cap: The capability to use
+ *
+ * Test to see if the opener of the socket we received the message
+ * from had when the netlink socket was created and the sender of the
+ * message has has the capability @cap over the network namespace of
+ * the socket we received the message from.
+ */
+bool netlink_net_capable(const struct sk_buff *skb, int cap)
+{
+ return netlink_ns_capable(skb, sock_net(skb->sk)->user_ns, cap);
+}
+EXPORT_SYMBOL(netlink_net_capable);
+
+static inline int netlink_allowed(const struct socket *sock, unsigned int flag)
{
return (nl_table[sock->sk->sk_protocol].flags & flag) ||
ns_capable(sock_net(sock->sk)->user_ns, CAP_NET_ADMIN);
@@ -1428,7 +1493,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
/* Only superuser is allowed to listen multicasts */
if (nladdr->nl_groups) {
- if (!netlink_capable(sock, NL_CFG_F_NONROOT_RECV))
+ if (!netlink_allowed(sock, NL_CFG_F_NONROOT_RECV))
return -EPERM;
err = netlink_realloc_groups(sk);
if (err)
@@ -1490,7 +1555,7 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr,
return -EINVAL;
if ((nladdr->nl_groups || nladdr->nl_pid) &&
- !netlink_capable(sock, NL_CFG_F_NONROOT_SEND))
+ !netlink_allowed(sock, NL_CFG_F_NONROOT_SEND))
return -EPERM;
if (!nlk->portid)
@@ -2096,7 +2161,7 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname,
break;
case NETLINK_ADD_MEMBERSHIP:
case NETLINK_DROP_MEMBERSHIP: {
- if (!netlink_capable(sock, NL_CFG_F_NONROOT_RECV))
+ if (!netlink_allowed(sock, NL_CFG_F_NONROOT_RECV))
return -EPERM;
err = netlink_realloc_groups(sk);
if (err)
@@ -2247,7 +2312,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
dst_group = ffs(addr->nl_groups);
err = -EPERM;
if ((dst_group || dst_portid) &&
- !netlink_capable(sock, NL_CFG_F_NONROOT_SEND))
+ !netlink_allowed(sock, NL_CFG_F_NONROOT_SEND))
goto out;
} else {
dst_portid = nlk->dst_portid;
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index b1dcdb932a86..a3ba3ca0ff92 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -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) {
diff --git a/net/openvswitch/vport-gre.c b/net/openvswitch/vport-gre.c
index a3d6951602db..ebb6e2442554 100644
--- a/net/openvswitch/vport-gre.c
+++ b/net/openvswitch/vport-gre.c
@@ -174,7 +174,7 @@ static int gre_tnl_send(struct vport *vport, struct sk_buff *skb)
skb->local_df = 1;
- return iptunnel_xmit(rt, skb, fl.saddr,
+ return iptunnel_xmit(skb->sk, rt, skb, fl.saddr,
OVS_CB(skb)->tun_key->ipv4_dst, IPPROTO_GRE,
OVS_CB(skb)->tun_key->ipv4_tos,
OVS_CB(skb)->tun_key->ipv4_ttl, df, false);
diff --git a/net/packet/diag.c b/net/packet/diag.c
index 533ce4ff108a..92f2c7107eec 100644
--- a/net/packet/diag.c
+++ b/net/packet/diag.c
@@ -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,
diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c
index dc15f4300808..b64151ade6b3 100644
--- a/net/phonet/pn_netlink.c
+++ b/net/phonet/pn_netlink.c
@@ -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();
diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c
index 7633a752c65e..0ad080790a32 100644
--- a/net/rxrpc/ar-key.c
+++ b/net/rxrpc/ar-key.c
@@ -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;
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 8a5ba5add4bc..648778aef1a2 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -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);
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 29a30a14c315..bdbdb1a7920a 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -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:
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c
index eed8404443d8..f435a88d899a 100644
--- a/net/sched/cls_tcindex.c
+++ b/net/sched/cls_tcindex.c
@@ -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;
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index a0b84e0e22de..400769014bbd 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -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);
diff --git a/net/sched/sch_hhf.c b/net/sched/sch_hhf.c
index edee03d922e2..6e957c3b9854 100644
--- a/net/sched/sch_hhf.c
+++ b/net/sched/sch_hhf.c
@@ -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;
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 4f6d6f9d1274..39579c3e0d14 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -1395,35 +1395,44 @@ static inline bool sctp_peer_needs_update(struct sctp_association *asoc)
return false;
}
-/* Update asoc's rwnd for the approximated state in the buffer,
- * and check whether SACK needs to be sent.
- */
-void sctp_assoc_rwnd_update(struct sctp_association *asoc, bool update_peer)
+/* Increase asoc's rwnd by len and send any window update SACK if needed. */
+void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned int len)
{
- int rx_count;
struct sctp_chunk *sack;
struct timer_list *timer;
- if (asoc->ep->rcvbuf_policy)
- rx_count = atomic_read(&asoc->rmem_alloc);
- else
- rx_count = atomic_read(&asoc->base.sk->sk_rmem_alloc);
+ if (asoc->rwnd_over) {
+ if (asoc->rwnd_over >= len) {
+ asoc->rwnd_over -= len;
+ } else {
+ asoc->rwnd += (len - asoc->rwnd_over);
+ asoc->rwnd_over = 0;
+ }
+ } else {
+ asoc->rwnd += len;
+ }
- if ((asoc->base.sk->sk_rcvbuf - rx_count) > 0)
- asoc->rwnd = (asoc->base.sk->sk_rcvbuf - rx_count) >> 1;
- else
- asoc->rwnd = 0;
+ /* If we had window pressure, start recovering it
+ * once our rwnd had reached the accumulated pressure
+ * threshold. The idea is to recover slowly, but up
+ * to the initial advertised window.
+ */
+ if (asoc->rwnd_press && asoc->rwnd >= asoc->rwnd_press) {
+ int change = min(asoc->pathmtu, asoc->rwnd_press);
+ asoc->rwnd += change;
+ asoc->rwnd_press -= change;
+ }
- pr_debug("%s: asoc:%p rwnd=%u, rx_count=%d, sk_rcvbuf=%d\n",
- __func__, asoc, asoc->rwnd, rx_count,
- asoc->base.sk->sk_rcvbuf);
+ pr_debug("%s: asoc:%p rwnd increased by %d to (%u, %u) - %u\n",
+ __func__, asoc, len, asoc->rwnd, asoc->rwnd_over,
+ asoc->a_rwnd);
/* Send a window update SACK if the rwnd has increased by at least the
* minimum of the association's PMTU and half of the receive buffer.
* The algorithm used is similar to the one described in
* Section 4.2.3.3 of RFC 1122.
*/
- if (update_peer && sctp_peer_needs_update(asoc)) {
+ if (sctp_peer_needs_update(asoc)) {
asoc->a_rwnd = asoc->rwnd;
pr_debug("%s: sending window update SACK- asoc:%p rwnd:%u "
@@ -1445,6 +1454,45 @@ void sctp_assoc_rwnd_update(struct sctp_association *asoc, bool update_peer)
}
}
+/* Decrease asoc's rwnd by len. */
+void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned int len)
+{
+ int rx_count;
+ int over = 0;
+
+ if (unlikely(!asoc->rwnd || asoc->rwnd_over))
+ pr_debug("%s: association:%p has asoc->rwnd:%u, "
+ "asoc->rwnd_over:%u!\n", __func__, asoc,
+ asoc->rwnd, asoc->rwnd_over);
+
+ if (asoc->ep->rcvbuf_policy)
+ rx_count = atomic_read(&asoc->rmem_alloc);
+ else
+ rx_count = atomic_read(&asoc->base.sk->sk_rmem_alloc);
+
+ /* If we've reached or overflowed our receive buffer, announce
+ * a 0 rwnd if rwnd would still be positive. Store the
+ * the potential pressure overflow so that the window can be restored
+ * back to original value.
+ */
+ if (rx_count >= asoc->base.sk->sk_rcvbuf)
+ over = 1;
+
+ if (asoc->rwnd >= len) {
+ asoc->rwnd -= len;
+ if (over) {
+ asoc->rwnd_press += asoc->rwnd;
+ asoc->rwnd = 0;
+ }
+ } else {
+ asoc->rwnd_over = len - asoc->rwnd;
+ asoc->rwnd = 0;
+ }
+
+ pr_debug("%s: asoc:%p rwnd decreased by %d to (%u, %u, %u)\n",
+ __func__, asoc, len, asoc->rwnd, asoc->rwnd_over,
+ asoc->rwnd_press);
+}
/* Build the bind address list for the association based on info from the
* local endpoint and the remote peer.
diff --git a/net/sctp/auth.c b/net/sctp/auth.c
index 683c7d1b1306..0e8529113dc5 100644
--- a/net/sctp/auth.c
+++ b/net/sctp/auth.c
@@ -386,14 +386,13 @@ nomem:
*/
int sctp_auth_asoc_init_active_key(struct sctp_association *asoc, gfp_t gfp)
{
- struct net *net = sock_net(asoc->base.sk);
struct sctp_auth_bytes *secret;
struct sctp_shared_key *ep_key;
/* If we don't support AUTH, or peer is not capable
* we don't need to do anything.
*/
- if (!net->sctp.auth_enable || !asoc->peer.auth_capable)
+ if (!asoc->ep->auth_enable || !asoc->peer.auth_capable)
return 0;
/* If the key_id is non-zero and we couldn't find an
@@ -440,16 +439,16 @@ struct sctp_shared_key *sctp_auth_get_shkey(
*/
int sctp_auth_init_hmacs(struct sctp_endpoint *ep, gfp_t gfp)
{
- struct net *net = sock_net(ep->base.sk);
struct crypto_hash *tfm = NULL;
__u16 id;
- /* if the transforms are already allocted, we are done */
- if (!net->sctp.auth_enable) {
+ /* If AUTH extension is disabled, we are done */
+ if (!ep->auth_enable) {
ep->auth_hmacs = NULL;
return 0;
}
+ /* If the transforms are already allocated, we are done */
if (ep->auth_hmacs)
return 0;
@@ -665,12 +664,10 @@ static int __sctp_auth_cid(sctp_cid_t chunk, struct sctp_chunks_param *param)
/* Check if peer requested that this chunk is authenticated */
int sctp_auth_send_cid(sctp_cid_t chunk, const struct sctp_association *asoc)
{
- struct net *net;
if (!asoc)
return 0;
- net = sock_net(asoc->base.sk);
- if (!net->sctp.auth_enable || !asoc->peer.auth_capable)
+ if (!asoc->ep->auth_enable || !asoc->peer.auth_capable)
return 0;
return __sctp_auth_cid(chunk, asoc->peer.peer_chunks);
@@ -679,12 +676,10 @@ int sctp_auth_send_cid(sctp_cid_t chunk, const struct sctp_association *asoc)
/* Check if we requested that peer authenticate this chunk. */
int sctp_auth_recv_cid(sctp_cid_t chunk, const struct sctp_association *asoc)
{
- struct net *net;
if (!asoc)
return 0;
- net = sock_net(asoc->base.sk);
- if (!net->sctp.auth_enable)
+ if (!asoc->ep->auth_enable)
return 0;
return __sctp_auth_cid(chunk,
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 8e5fdea05216..3d9f429858dc 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -68,7 +68,8 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
if (!ep->digest)
return NULL;
- if (net->sctp.auth_enable) {
+ ep->auth_enable = net->sctp.auth_enable;
+ if (ep->auth_enable) {
/* Allocate space for HMACS and CHUNKS authentication
* variables. There are arrays that we encode directly
* into parameters to make the rest of the operations easier.
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 4e1d0fcb028e..44cbb54c8574 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -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;
@@ -957,7 +962,7 @@ static inline int sctp_v4_xmit(struct sk_buff *skb,
SCTP_INC_STATS(sock_net(&inet->sk), SCTP_MIB_OUTSCTPPACKS);
- return ip_queue_xmit(skb, &transport->fl);
+ return ip_queue_xmit(&inet->sk, skb, &transport->fl);
}
static struct sctp_af sctp_af_inet;
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 3a1767ef3201..fee5552ddf92 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -219,6 +219,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
gfp_t gfp, int vparam_len)
{
struct net *net = sock_net(asoc->base.sk);
+ struct sctp_endpoint *ep = asoc->ep;
sctp_inithdr_t init;
union sctp_params addrs;
size_t chunksize;
@@ -278,7 +279,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
chunksize += vparam_len;
/* Account for AUTH related parameters */
- if (net->sctp.auth_enable) {
+ if (ep->auth_enable) {
/* Add random parameter length*/
chunksize += sizeof(asoc->c.auth_random);
@@ -363,7 +364,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
}
/* Add SCTP-AUTH chunks to the parameter list */
- if (net->sctp.auth_enable) {
+ if (ep->auth_enable) {
sctp_addto_chunk(retval, sizeof(asoc->c.auth_random),
asoc->c.auth_random);
if (auth_hmacs)
@@ -2010,7 +2011,7 @@ static void sctp_process_ext_param(struct sctp_association *asoc,
/* if the peer reports AUTH, assume that he
* supports AUTH.
*/
- if (net->sctp.auth_enable)
+ if (asoc->ep->auth_enable)
asoc->peer.auth_capable = 1;
break;
case SCTP_CID_ASCONF:
@@ -2102,6 +2103,7 @@ static sctp_ierror_t sctp_process_unk_param(const struct sctp_association *asoc,
* SCTP_IERROR_NO_ERROR - continue with the chunk
*/
static sctp_ierror_t sctp_verify_param(struct net *net,
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
union sctp_params param,
sctp_cid_t cid,
@@ -2152,7 +2154,7 @@ static sctp_ierror_t sctp_verify_param(struct net *net,
goto fallthrough;
case SCTP_PARAM_RANDOM:
- if (!net->sctp.auth_enable)
+ if (!ep->auth_enable)
goto fallthrough;
/* SCTP-AUTH: Secion 6.1
@@ -2169,7 +2171,7 @@ static sctp_ierror_t sctp_verify_param(struct net *net,
break;
case SCTP_PARAM_CHUNKS:
- if (!net->sctp.auth_enable)
+ if (!ep->auth_enable)
goto fallthrough;
/* SCTP-AUTH: Section 3.2
@@ -2185,7 +2187,7 @@ static sctp_ierror_t sctp_verify_param(struct net *net,
break;
case SCTP_PARAM_HMAC_ALGO:
- if (!net->sctp.auth_enable)
+ if (!ep->auth_enable)
goto fallthrough;
hmacs = (struct sctp_hmac_algo_param *)param.p;
@@ -2220,10 +2222,9 @@ fallthrough:
}
/* Verify the INIT packet before we process it. */
-int sctp_verify_init(struct net *net, const struct sctp_association *asoc,
- sctp_cid_t cid,
- sctp_init_chunk_t *peer_init,
- struct sctp_chunk *chunk,
+int sctp_verify_init(struct net *net, const struct sctp_endpoint *ep,
+ const struct sctp_association *asoc, sctp_cid_t cid,
+ sctp_init_chunk_t *peer_init, struct sctp_chunk *chunk,
struct sctp_chunk **errp)
{
union sctp_params param;
@@ -2264,8 +2265,8 @@ int sctp_verify_init(struct net *net, const struct sctp_association *asoc,
/* Verify all the variable length parameters */
sctp_walk_params(param, peer_init, init_hdr.params) {
-
- result = sctp_verify_param(net, asoc, param, cid, chunk, errp);
+ result = sctp_verify_param(net, ep, asoc, param, cid,
+ chunk, errp);
switch (result) {
case SCTP_IERROR_ABORT:
case SCTP_IERROR_NOMEM:
@@ -2497,6 +2498,7 @@ static int sctp_process_param(struct sctp_association *asoc,
struct sctp_af *af;
union sctp_addr_param *addr_param;
struct sctp_transport *t;
+ struct sctp_endpoint *ep = asoc->ep;
/* We maintain all INIT parameters in network byte order all the
* time. This allows us to not worry about whether the parameters
@@ -2636,7 +2638,7 @@ do_addr_param:
goto fall_through;
case SCTP_PARAM_RANDOM:
- if (!net->sctp.auth_enable)
+ if (!ep->auth_enable)
goto fall_through;
/* Save peer's random parameter */
@@ -2649,7 +2651,7 @@ do_addr_param:
break;
case SCTP_PARAM_HMAC_ALGO:
- if (!net->sctp.auth_enable)
+ if (!ep->auth_enable)
goto fall_through;
/* Save peer's HMAC list */
@@ -2665,7 +2667,7 @@ do_addr_param:
break;
case SCTP_PARAM_CHUNKS:
- if (!net->sctp.auth_enable)
+ if (!ep->auth_enable)
goto fall_through;
asoc->peer.peer_chunks = kmemdup(param.p,
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 5d6883ff00c3..fef2acdf4a2e 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -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)) {
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 01e002430c85..5170a1ff95a1 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -357,7 +357,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(struct net *net,
/* Verify the INIT chunk before processing it. */
err_chunk = NULL;
- if (!sctp_verify_init(net, asoc, chunk->chunk_hdr->type,
+ if (!sctp_verify_init(net, ep, asoc, chunk->chunk_hdr->type,
(sctp_init_chunk_t *)chunk->chunk_hdr, chunk,
&err_chunk)) {
/* This chunk contains fatal error. It is to be discarded.
@@ -524,7 +524,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(struct net *net,
/* Verify the INIT chunk before processing it. */
err_chunk = NULL;
- if (!sctp_verify_init(net, asoc, chunk->chunk_hdr->type,
+ if (!sctp_verify_init(net, ep, asoc, chunk->chunk_hdr->type,
(sctp_init_chunk_t *)chunk->chunk_hdr, chunk,
&err_chunk)) {
@@ -1430,7 +1430,7 @@ static sctp_disposition_t sctp_sf_do_unexpected_init(
/* Verify the INIT chunk before processing it. */
err_chunk = NULL;
- if (!sctp_verify_init(net, asoc, chunk->chunk_hdr->type,
+ if (!sctp_verify_init(net, ep, asoc, chunk->chunk_hdr->type,
(sctp_init_chunk_t *)chunk->chunk_hdr, chunk,
&err_chunk)) {
/* This chunk contains fatal error. It is to be discarded.
@@ -6178,7 +6178,7 @@ static int sctp_eat_data(const struct sctp_association *asoc,
* PMTU. In cases, such as loopback, this might be a rather
* large spill over.
*/
- if ((!chunk->data_accepted) && (!asoc->rwnd ||
+ if ((!chunk->data_accepted) && (!asoc->rwnd || asoc->rwnd_over ||
(datalen > asoc->rwnd + asoc->frag_point))) {
/* If this is the next TSN, consider reneging to make
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index e13519e9df80..fee06b99a4da 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -2115,6 +2115,12 @@ static int sctp_recvmsg(struct kiocb *iocb, struct sock *sk,
sctp_skb_pull(skb, copied);
skb_queue_head(&sk->sk_receive_queue, skb);
+ /* When only partial message is copied to the user, increase
+ * rwnd by that amount. If all the data in the skb is read,
+ * rwnd is updated when the event is freed.
+ */
+ if (!sctp_ulpevent_is_notification(event))
+ sctp_assoc_rwnd_increase(event->asoc, copied);
goto out;
} else if ((event->msg_flags & MSG_NOTIFICATION) ||
(event->msg_flags & MSG_EOR))
@@ -3315,10 +3321,10 @@ static int sctp_setsockopt_auth_chunk(struct sock *sk,
char __user *optval,
unsigned int optlen)
{
- struct net *net = sock_net(sk);
+ struct sctp_endpoint *ep = sctp_sk(sk)->ep;
struct sctp_authchunk val;
- if (!net->sctp.auth_enable)
+ if (!ep->auth_enable)
return -EACCES;
if (optlen != sizeof(struct sctp_authchunk))
@@ -3335,7 +3341,7 @@ static int sctp_setsockopt_auth_chunk(struct sock *sk,
}
/* add this chunk id to the endpoint */
- return sctp_auth_ep_add_chunkid(sctp_sk(sk)->ep, val.sauth_chunk);
+ return sctp_auth_ep_add_chunkid(ep, val.sauth_chunk);
}
/*
@@ -3348,12 +3354,12 @@ static int sctp_setsockopt_hmac_ident(struct sock *sk,
char __user *optval,
unsigned int optlen)
{
- struct net *net = sock_net(sk);
+ struct sctp_endpoint *ep = sctp_sk(sk)->ep;
struct sctp_hmacalgo *hmacs;
u32 idents;
int err;
- if (!net->sctp.auth_enable)
+ if (!ep->auth_enable)
return -EACCES;
if (optlen < sizeof(struct sctp_hmacalgo))
@@ -3370,7 +3376,7 @@ static int sctp_setsockopt_hmac_ident(struct sock *sk,
goto out;
}
- err = sctp_auth_ep_set_hmacs(sctp_sk(sk)->ep, hmacs);
+ err = sctp_auth_ep_set_hmacs(ep, hmacs);
out:
kfree(hmacs);
return err;
@@ -3386,12 +3392,12 @@ static int sctp_setsockopt_auth_key(struct sock *sk,
char __user *optval,
unsigned int optlen)
{
- struct net *net = sock_net(sk);
+ struct sctp_endpoint *ep = sctp_sk(sk)->ep;
struct sctp_authkey *authkey;
struct sctp_association *asoc;
int ret;
- if (!net->sctp.auth_enable)
+ if (!ep->auth_enable)
return -EACCES;
if (optlen <= sizeof(struct sctp_authkey))
@@ -3412,7 +3418,7 @@ static int sctp_setsockopt_auth_key(struct sock *sk,
goto out;
}
- ret = sctp_auth_set_key(sctp_sk(sk)->ep, asoc, authkey);
+ ret = sctp_auth_set_key(ep, asoc, authkey);
out:
kzfree(authkey);
return ret;
@@ -3428,11 +3434,11 @@ static int sctp_setsockopt_active_key(struct sock *sk,
char __user *optval,
unsigned int optlen)
{
- struct net *net = sock_net(sk);
+ struct sctp_endpoint *ep = sctp_sk(sk)->ep;
struct sctp_authkeyid val;
struct sctp_association *asoc;
- if (!net->sctp.auth_enable)
+ if (!ep->auth_enable)
return -EACCES;
if (optlen != sizeof(struct sctp_authkeyid))
@@ -3444,8 +3450,7 @@ static int sctp_setsockopt_active_key(struct sock *sk,
if (!asoc && val.scact_assoc_id && sctp_style(sk, UDP))
return -EINVAL;
- return sctp_auth_set_active_key(sctp_sk(sk)->ep, asoc,
- val.scact_keynumber);
+ return sctp_auth_set_active_key(ep, asoc, val.scact_keynumber);
}
/*
@@ -3457,11 +3462,11 @@ static int sctp_setsockopt_del_key(struct sock *sk,
char __user *optval,
unsigned int optlen)
{
- struct net *net = sock_net(sk);
+ struct sctp_endpoint *ep = sctp_sk(sk)->ep;
struct sctp_authkeyid val;
struct sctp_association *asoc;
- if (!net->sctp.auth_enable)
+ if (!ep->auth_enable)
return -EACCES;
if (optlen != sizeof(struct sctp_authkeyid))
@@ -3473,8 +3478,7 @@ static int sctp_setsockopt_del_key(struct sock *sk,
if (!asoc && val.scact_assoc_id && sctp_style(sk, UDP))
return -EINVAL;
- return sctp_auth_del_key_id(sctp_sk(sk)->ep, asoc,
- val.scact_keynumber);
+ return sctp_auth_del_key_id(ep, asoc, val.scact_keynumber);
}
@@ -5381,16 +5385,16 @@ static int sctp_getsockopt_maxburst(struct sock *sk, int len,
static int sctp_getsockopt_hmac_ident(struct sock *sk, int len,
char __user *optval, int __user *optlen)
{
- struct net *net = sock_net(sk);
+ struct sctp_endpoint *ep = sctp_sk(sk)->ep;
struct sctp_hmacalgo __user *p = (void __user *)optval;
struct sctp_hmac_algo_param *hmacs;
__u16 data_len = 0;
u32 num_idents;
- if (!net->sctp.auth_enable)
+ if (!ep->auth_enable)
return -EACCES;
- hmacs = sctp_sk(sk)->ep->auth_hmacs_list;
+ hmacs = ep->auth_hmacs_list;
data_len = ntohs(hmacs->param_hdr.length) - sizeof(sctp_paramhdr_t);
if (len < sizeof(struct sctp_hmacalgo) + data_len)
@@ -5411,11 +5415,11 @@ static int sctp_getsockopt_hmac_ident(struct sock *sk, int len,
static int sctp_getsockopt_active_key(struct sock *sk, int len,
char __user *optval, int __user *optlen)
{
- struct net *net = sock_net(sk);
+ struct sctp_endpoint *ep = sctp_sk(sk)->ep;
struct sctp_authkeyid val;
struct sctp_association *asoc;
- if (!net->sctp.auth_enable)
+ if (!ep->auth_enable)
return -EACCES;
if (len < sizeof(struct sctp_authkeyid))
@@ -5430,7 +5434,7 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len,
if (asoc)
val.scact_keynumber = asoc->active_key_id;
else
- val.scact_keynumber = sctp_sk(sk)->ep->active_key_id;
+ val.scact_keynumber = ep->active_key_id;
len = sizeof(struct sctp_authkeyid);
if (put_user(len, optlen))
@@ -5444,7 +5448,7 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len,
static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len,
char __user *optval, int __user *optlen)
{
- struct net *net = sock_net(sk);
+ struct sctp_endpoint *ep = sctp_sk(sk)->ep;
struct sctp_authchunks __user *p = (void __user *)optval;
struct sctp_authchunks val;
struct sctp_association *asoc;
@@ -5452,7 +5456,7 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len,
u32 num_chunks = 0;
char __user *to;
- if (!net->sctp.auth_enable)
+ if (!ep->auth_enable)
return -EACCES;
if (len < sizeof(struct sctp_authchunks))
@@ -5489,7 +5493,7 @@ num:
static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len,
char __user *optval, int __user *optlen)
{
- struct net *net = sock_net(sk);
+ struct sctp_endpoint *ep = sctp_sk(sk)->ep;
struct sctp_authchunks __user *p = (void __user *)optval;
struct sctp_authchunks val;
struct sctp_association *asoc;
@@ -5497,7 +5501,7 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len,
u32 num_chunks = 0;
char __user *to;
- if (!net->sctp.auth_enable)
+ if (!ep->auth_enable)
return -EACCES;
if (len < sizeof(struct sctp_authchunks))
@@ -5514,7 +5518,7 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len,
if (asoc)
ch = (struct sctp_chunks_param *)asoc->c.auth_chunks;
else
- ch = sctp_sk(sk)->ep->auth_chunk_list;
+ ch = ep->auth_chunk_list;
if (!ch)
goto num;
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index 35c8923b5554..c82fdc1eab7c 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -64,6 +64,9 @@ static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write,
static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write,
void __user *buffer, size_t *lenp,
loff_t *ppos);
+static int proc_sctp_do_auth(struct ctl_table *ctl, int write,
+ void __user *buffer, size_t *lenp,
+ loff_t *ppos);
static struct ctl_table sctp_table[] = {
{
@@ -266,7 +269,7 @@ static struct ctl_table sctp_net_table[] = {
.data = &init_net.sctp.auth_enable,
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = proc_dointvec,
+ .proc_handler = proc_sctp_do_auth,
},
{
.procname = "addr_scope_policy",
@@ -400,6 +403,37 @@ static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write,
return ret;
}
+static int proc_sctp_do_auth(struct ctl_table *ctl, int write,
+ void __user *buffer, size_t *lenp,
+ loff_t *ppos)
+{
+ struct net *net = current->nsproxy->net_ns;
+ struct ctl_table tbl;
+ int new_value, ret;
+
+ memset(&tbl, 0, sizeof(struct ctl_table));
+ tbl.maxlen = sizeof(unsigned int);
+
+ if (write)
+ tbl.data = &new_value;
+ else
+ tbl.data = &net->sctp.auth_enable;
+
+ ret = proc_dointvec(&tbl, write, buffer, lenp, ppos);
+
+ if (write) {
+ struct sock *sk = net->sctp.ctl_sock;
+
+ net->sctp.auth_enable = new_value;
+ /* Update the value in the control socket */
+ lock_sock(sk);
+ sctp_sk(sk)->ep->auth_enable = new_value;
+ release_sock(sk);
+ }
+
+ return ret;
+}
+
int sctp_sysctl_net_register(struct net *net)
{
struct ctl_table *table = sctp_net_table;
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index 8d198ae03606..85c64658bd0b 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -989,7 +989,7 @@ static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event,
skb = sctp_event2skb(event);
/* Set the owner and charge rwnd for bytes received. */
sctp_ulpevent_set_owner(event, asoc);
- sctp_assoc_rwnd_update(asoc, false);
+ sctp_assoc_rwnd_decrease(asoc, skb_headlen(skb));
if (!skb->data_len)
return;
@@ -1011,7 +1011,6 @@ static void sctp_ulpevent_release_data(struct sctp_ulpevent *event)
{
struct sk_buff *skb, *frag;
unsigned int len;
- struct sctp_association *asoc;
/* Current stack structures assume that the rcv buffer is
* per socket. For UDP style sockets this is not true as
@@ -1036,11 +1035,8 @@ static void sctp_ulpevent_release_data(struct sctp_ulpevent *event)
}
done:
- asoc = event->asoc;
- sctp_association_hold(asoc);
+ sctp_assoc_rwnd_increase(event->asoc, len);
sctp_ulpevent_release_owner(event);
- sctp_assoc_rwnd_update(asoc, true);
- sctp_association_put(asoc);
}
static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event)
diff --git a/net/socket.c b/net/socket.c
index 1b1e7e6a960f..abf56b2a14f9 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1880,8 +1880,8 @@ out:
* Receive a datagram from a socket.
*/
-asmlinkage long sys_recv(int fd, void __user *ubuf, size_t size,
- unsigned int flags)
+SYSCALL_DEFINE4(recv, int, fd, void __user *, ubuf, size_t, size,
+ unsigned int, flags)
{
return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL);
}
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index 3aaf73de9e2d..ad844d365340 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -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;
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index 5adfd94c5b85..85d232bed87d 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -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");
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 7d09a712cb1f..88f108edfb58 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -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);
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index acdcb4a81817..3546a77033de 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -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;
}
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index f02f511b7107..c08fbd11ceff 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1842,7 +1842,7 @@ purge_queue:
xfrm_pol_put(pol);
}
-static int xdst_queue_output(struct sk_buff *skb)
+static int xdst_queue_output(struct sock *sk, struct sk_buff *skb)
{
unsigned long sched_next;
struct dst_entry *dst = skb_dst(skb);
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 8f131c10a6f3..51398ae6cda8 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -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) ||
diff --git a/scripts/checksyscalls.sh b/scripts/checksyscalls.sh
index fd8fa9aa7c4e..5b3add31f9f1 100755
--- a/scripts/checksyscalls.sh
+++ b/scripts/checksyscalls.sh
@@ -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 */
diff --git a/scripts/sortextable.c b/scripts/sortextable.c
index cc49062acdee..1052d4834a44 100644
--- a/scripts/sortextable.c
+++ b/scripts/sortextable.c
@@ -35,6 +35,10 @@
#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 */
diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h
index 8fb1488a3cd4..97130f88838b 100644
--- a/security/apparmor/include/apparmor.h
+++ b/security/apparmor/include/apparmor.h
@@ -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)
{
diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c
index 69689922c491..c1827e068454 100644
--- a/security/apparmor/lib.c
+++ b/security/apparmor/lib.c
@@ -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);
-}
diff --git a/security/device_cgroup.c b/security/device_cgroup.c
index 8365909f5f8c..9134dbf70d3e 100644
--- a/security/device_cgroup.c
+++ b/security/device_cgroup.c
@@ -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)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index b4beb77967b1..2c7341dbc5d6 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3317,9 +3317,9 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd,
case F_GETLK:
case F_SETLK:
case F_SETLKW:
- case F_GETLKP:
- case F_SETLKP:
- case F_SETLKPW:
+ case F_OFD_GETLK:
+ case F_OFD_SETLK:
+ case F_OFD_SETLKW:
#if BITS_PER_LONG == 32
case F_GETLK64:
case F_SETLK64:
diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c
index 94d08733cb38..76cbb9ec953a 100644
--- a/sound/core/pcm_dmaengine.c
+++ b/sound/core/pcm_dmaengine.c
@@ -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;
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
index 1c16830af3d8..6faaac60161a 100644
--- a/sound/isa/es18xx.c
+++ b/sound/isa/es18xx.c
@@ -520,7 +520,7 @@ static int snd_es18xx_playback1_trigger(struct snd_es18xx *chip,
snd_es18xx_mixer_write(chip, 0x78, 0x93);
#ifdef AVOID_POPS
/* Avoid pops */
- udelay(100000);
+ mdelay(100);
if (chip->caps & ES18XX_PCM2)
/* Restore Audio 2 volume */
snd_es18xx_mixer_write(chip, 0x7C, chip->audio2_vol);
@@ -537,7 +537,7 @@ static int snd_es18xx_playback1_trigger(struct snd_es18xx *chip,
/* Stop DMA */
snd_es18xx_mixer_write(chip, 0x78, 0x00);
#ifdef AVOID_POPS
- udelay(25000);
+ mdelay(25);
if (chip->caps & ES18XX_PCM2)
/* Set Audio 2 volume to 0 */
snd_es18xx_mixer_write(chip, 0x7C, 0);
@@ -596,7 +596,7 @@ static int snd_es18xx_capture_prepare(struct snd_pcm_substream *substream)
snd_es18xx_write(chip, 0xA5, count >> 8);
#ifdef AVOID_POPS
- udelay(100000);
+ mdelay(100);
#endif
/* Set format */
@@ -691,7 +691,7 @@ static int snd_es18xx_playback2_trigger(struct snd_es18xx *chip,
snd_es18xx_write(chip, 0xB8, 0x05);
#ifdef AVOID_POPS
/* Avoid pops */
- udelay(100000);
+ mdelay(100);
/* Enable Audio 1 */
snd_es18xx_dsp_command(chip, 0xD1);
#endif
@@ -705,7 +705,7 @@ static int snd_es18xx_playback2_trigger(struct snd_es18xx *chip,
snd_es18xx_write(chip, 0xB8, 0x00);
#ifdef AVOID_POPS
/* Avoid pops */
- udelay(25000);
+ mdelay(25);
/* Disable Audio 1 */
snd_es18xx_dsp_command(chip, 0xD3);
#endif
diff --git a/sound/isa/sb/sb_mixer.c b/sound/isa/sb/sb_mixer.c
index 6496822c1808..1ff78ec9f0ac 100644
--- a/sound/isa/sb/sb_mixer.c
+++ b/sound/isa/sb/sb_mixer.c
@@ -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, "???");
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c
index 248b90abb882..480bbddbd801 100644
--- a/sound/pci/hda/hda_controller.c
+++ b/sound/pci/hda/hda_controller.c
@@ -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);
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index d6bca62ef387..6cc3cf285558 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -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 },
diff --git a/sound/pci/hda/hda_priv.h b/sound/pci/hda/hda_priv.h
index ba38b819f984..4a7cb01fa912 100644
--- a/sound/pci/hda/hda_priv.h
+++ b/sound/pci/hda/hda_priv.h
@@ -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 {
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 0cb5b89cd0c8..b4218a19df22 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -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");
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 14ae979a92ea..49e884fb3e5d 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -4616,11 +4616,17 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1028, 0x0653, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0657, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0658, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1028, 0x065c, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x065f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0662, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0667, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0668, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0669, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1028, 0x0674, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1028, 0x067e, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1028, 0x067f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1028, 0x0680, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1028, 0x0684, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x15cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x15cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
@@ -4912,6 +4918,7 @@ static int patch_alc269(struct hda_codec *codec)
spec->codec_variant = ALC269_TYPE_ALC285;
break;
case 0x10ec0286:
+ case 0x10ec0288:
spec->codec_variant = ALC269_TYPE_ALC286;
break;
case 0x10ec0255:
@@ -5539,6 +5546,8 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0628, "Dell", ALC668_FIXUP_AUTO_MUTE),
SND_PCI_QUIRK(0x1028, 0x064e, "Dell", ALC668_FIXUP_AUTO_MUTE),
+ SND_PCI_QUIRK(0x1028, 0x0696, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1028, 0x0698, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_BASS_1A),
SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_MODE4_CHMAP),
@@ -5781,6 +5790,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = {
{ .id = 0x10ec0284, .name = "ALC284", .patch = patch_alc269 },
{ .id = 0x10ec0285, .name = "ALC285", .patch = patch_alc269 },
{ .id = 0x10ec0286, .name = "ALC286", .patch = patch_alc269 },
+ { .id = 0x10ec0288, .name = "ALC288", .patch = patch_alc269 },
{ .id = 0x10ec0290, .name = "ALC290", .patch = patch_alc269 },
{ .id = 0x10ec0292, .name = "ALC292", .patch = patch_alc269 },
{ .id = 0x10ec0293, .name = "ALC293", .patch = patch_alc269 },
diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c
index f500905e9373..2acf82f4a08a 100644
--- a/sound/soc/codecs/alc5623.c
+++ b/sound/soc/codecs/alc5623.c
@@ -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");
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c
index 460d35547a68..2213a037c893 100644
--- a/sound/soc/codecs/cs42l52.c
+++ b/sound/soc/codecs/cs42l52.c
@@ -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);
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c
index 0ee60a19a263..ae3717992d56 100644
--- a/sound/soc/codecs/cs42l73.c
+++ b/sound/soc/codecs/cs42l73.c
@@ -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);
diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c
index fa158cfe9b32..d1929de641e2 100644
--- a/sound/soc/codecs/tlv320aic31xx.c
+++ b/sound/soc/codecs/tlv320aic31xx.c
@@ -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;
}
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index b1835103e9b4..d7349bc89ad3 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -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) &&
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 5522d2566c67..ecd26dd2e442 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -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);
}
diff --git a/sound/soc/codecs/wm8962.h b/sound/soc/codecs/wm8962.h
index a1a5d5294c19..910aafd09d21 100644
--- a/sound/soc/codecs/wm8962.h
+++ b/sound/soc/codecs/wm8962.h
@@ -1954,6 +1954,10 @@
#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 */
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c
index c8e5db1414d7..496ce2eb2f1f 100644
--- a/sound/soc/fsl/fsl_esai.c
+++ b/sound/soc/fsl/fsl_esai.c
@@ -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;
}
diff --git a/sound/soc/fsl/fsl_spdif.h b/sound/soc/fsl/fsl_spdif.h
index b1266790d117..605a10b2112b 100644
--- a/sound/soc/fsl/fsl_spdif.h
+++ b/sound/soc/fsl/fsl_spdif.h
@@ -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)
diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c
index ac869931d7f1..267717aa96c1 100644
--- a/sound/soc/fsl/imx-audmux.c
+++ b/sound/soc/fsl/imx-audmux.c
@@ -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];
diff --git a/sound/soc/intel/sst-acpi.c b/sound/soc/intel/sst-acpi.c
index 5d06eecb6198..18aee77f8d4a 100644
--- a/sound/soc/intel/sst-acpi.c
+++ b/sound/soc/intel/sst-acpi.c
@@ -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;
diff --git a/sound/soc/intel/sst-baytrail-dsp.c b/sound/soc/intel/sst-baytrail-dsp.c
index a50bf7fc0e3a..adf0aca5aca6 100644
--- a/sound/soc/intel/sst-baytrail-dsp.c
+++ b/sound/soc/intel/sst-baytrail-dsp.c
@@ -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;
diff --git a/sound/soc/intel/sst-baytrail-ipc.c b/sound/soc/intel/sst-baytrail-ipc.c
index d0eaeee21be4..0d31dbbf4806 100644
--- a/sound/soc/intel/sst-baytrail-ipc.c
+++ b/sound/soc/intel/sst-baytrail-ipc.c
@@ -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;
}
diff --git a/sound/soc/intel/sst-dsp-priv.h b/sound/soc/intel/sst-dsp-priv.h
index fe8e81aad646..401213455497 100644
--- a/sound/soc/intel/sst-dsp-priv.h
+++ b/sound/soc/intel/sst-dsp-priv.h
@@ -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;
diff --git a/sound/soc/intel/sst-dsp.c b/sound/soc/intel/sst-dsp.c
index 0c129fd85ecf..0b715b20a2d7 100644
--- a/sound/soc/intel/sst-dsp.c
+++ b/sound/soc/intel/sst-dsp.c
@@ -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;
diff --git a/sound/soc/intel/sst-dsp.h b/sound/soc/intel/sst-dsp.h
index 74052b59485c..e44423be66c4 100644
--- a/sound/soc/intel/sst-dsp.h
+++ b/sound/soc/intel/sst-dsp.h
@@ -169,6 +169,7 @@ struct sst_pdata {
u32 dma_base;
u32 dma_size;
int dma_engine;
+ struct device *dma_dev;
/* DSP */
u32 id;
diff --git a/sound/soc/intel/sst-firmware.c b/sound/soc/intel/sst-firmware.c
index f7687107cf7f..928f228c38e7 100644
--- a/sound/soc/intel/sst-firmware.c
+++ b/sound/soc/intel/sst-firmware.c
@@ -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;
}
diff --git a/sound/soc/intel/sst-haswell-dsp.c b/sound/soc/intel/sst-haswell-dsp.c
index f5ebf36af889..535f517629fd 100644
--- a/sound/soc/intel/sst-haswell-dsp.c
+++ b/sound/soc/intel/sst-haswell-dsp.c
@@ -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;
diff --git a/sound/soc/intel/sst-haswell-ipc.c b/sound/soc/intel/sst-haswell-ipc.c
index f46bb4ddde6f..e7996b39a484 100644
--- a/sound/soc/intel/sst-haswell-ipc.c
+++ b/sound/soc/intel/sst-haswell-ipc.c
@@ -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;
diff --git a/sound/soc/intel/sst-haswell-ipc.h b/sound/soc/intel/sst-haswell-ipc.h
index d517929ccc38..2ac194a6d04b 100644
--- a/sound/soc/intel/sst-haswell-ipc.h
+++ b/sound/soc/intel/sst-haswell-ipc.h
@@ -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 */
diff --git a/sound/soc/intel/sst-haswell-pcm.c b/sound/soc/intel/sst-haswell-pcm.c
index 0a32dd13a23d..9d5f64a583a3 100644
--- a/sound/soc/intel/sst-haswell-pcm.c
+++ b/sound/soc/intel/sst-haswell-pcm.c
@@ -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;
diff --git a/sound/soc/jz4740/Makefile b/sound/soc/jz4740/Makefile
index be873c1b0c20..d32c540555c4 100644
--- a/sound/soc/jz4740/Makefile
+++ b/sound/soc/jz4740/Makefile
@@ -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
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index 215b668166be..89424470a1f3 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -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)
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c
index 6232b7d307aa..4d0720ed5a90 100644
--- a/sound/soc/sh/rcar/src.c
+++ b/sound/soc/sh/rcar/src.c
@@ -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;
}
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
index 4b7e20603dd7..1d8387c25bd8 100644
--- a/sound/soc/sh/rcar/ssi.c
+++ b/sound/soc/sh/rcar/ssi.c
@@ -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));
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index c8a780d0d057..6d6ceee447d5 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -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 */
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 2cedf09f6d96..a391de058037 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -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))
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 893d5a1afc3c..c3b5b7dca1c3 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -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;
}
diff --git a/sound/usb/card.h b/sound/usb/card.h
index 9867ab866857..97acb906acc2 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -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;
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index e70a87e0d9fe..289f582c9130 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -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
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 131336d40492..c62a1659106d 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -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);
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 25c4c7e217de..91d0380431b4 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -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 */
diff --git a/tools/Makefile b/tools/Makefile
index bcae806b0c39..9a617adc6675 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -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)
diff --git a/tools/hv/hv_fcopy_daemon.c b/tools/hv/hv_fcopy_daemon.c
index 4ecc4fd0bc1b..fba1c75aa484 100644
--- a/tools/hv/hv_fcopy_daemon.c
+++ b/tools/hv/hv_fcopy_daemon.c
@@ -82,8 +82,10 @@ static int hv_start_fcopy(struct hv_start_fcopy *smsg)
if (!access(target_fname, F_OK)) {
syslog(LOG_INFO, "File: %s exists", target_fname);
- if (!smsg->copy_flags & OVER_WRITE)
+ if (!(smsg->copy_flags & OVER_WRITE)) {
+ error = HV_ERROR_ALREADY_EXISTS;
goto done;
+ }
}
target_fd = open(target_fname, O_RDWR | O_CREAT | O_CLOEXEC, 0744);
diff --git a/tools/lib/api/fs/debugfs.c b/tools/lib/api/fs/debugfs.c
index 7c4347962353..a74fba6d7743 100644
--- a/tools/lib/api/fs/debugfs.c
+++ b/tools/lib/api/fs/debugfs.c
@@ -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,
};
diff --git a/tools/lib/lockdep/Makefile b/tools/lib/lockdep/Makefile
index 07b0b7542511..bba2f5253b6e 100644
--- a/tools/lib/lockdep/Makefile
+++ b/tools/lib/lockdep/Makefile
@@ -1,13 +1,7 @@
-# liblockdep version
-LL_VERSION = 0
-LL_PATCHLEVEL = 0
-LL_EXTRAVERSION = 1
-
# file format version
FILE_VERSION = 1
-MAKEFLAGS += --no-print-directory
-
+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
@@ -98,7 +92,7 @@ export prefix libdir bindir src obj
libdir_SQ = $(subst ','\'',$(libdir))
bindir_SQ = $(subst ','\'',$(bindir))
-LIB_FILE = liblockdep.a liblockdep.so
+LIB_FILE = liblockdep.a liblockdep.so.$(LIBLOCKDEP_VERSION)
BIN_FILE = lockdep
CONFIG_INCLUDES =
@@ -110,8 +104,6 @@ N =
export Q VERBOSE
-LIBLOCKDEP_VERSION = $(LL_VERSION).$(LL_PATCHLEVEL).$(LL_EXTRAVERSION)
-
INCLUDES = -I. -I/usr/local/include -I./uinclude -I./include $(CONFIG_INCLUDES)
# Set compile option CFLAGS if not set elsewhere
@@ -146,7 +138,7 @@ do_app_build = \
do_compile_shared_library = \
($(print_shared_lib_compile) \
- $(CC) --shared $^ -o $@ -lpthread -ldl)
+ $(CC) --shared $^ -o $@ -lpthread -ldl -Wl,-soname='"$@"';$(shell ln -s $@ liblockdep.so))
do_build_static_lib = \
($(print_static_lib_build) \
@@ -177,7 +169,7 @@ all: all_cmd
all_cmd: $(CMD_TARGETS)
-liblockdep.so: $(PEVENT_LIB_OBJS)
+liblockdep.so.$(LIBLOCKDEP_VERSION): $(PEVENT_LIB_OBJS)
$(Q)$(do_compile_shared_library)
liblockdep.a: $(PEVENT_LIB_OBJS)
@@ -238,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
diff --git a/tools/lib/lockdep/uinclude/linux/lockdep.h b/tools/lib/lockdep/uinclude/linux/lockdep.h
index d0f5d6e50214..c1552c28507e 100644
--- a/tools/lib/lockdep/uinclude/linux/lockdep.h
+++ b/tools/lib/lockdep/uinclude/linux/lockdep.h
@@ -10,6 +10,9 @@
#define MAX_LOCK_DEPTH 2000UL
+#define asmlinkage
+#define __visible
+
#include "../../../include/linux/lockdep.h"
struct task_struct {
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index 1587ea392ad6..b83184f2d484 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -50,6 +50,18 @@ static int show_warning = 1;
warning(fmt, ##__VA_ARGS__); \
} while (0)
+#define do_warning_event(event, fmt, ...) \
+ do { \
+ if (!show_warning) \
+ continue; \
+ \
+ if (event) \
+ warning("[%s:%s] " fmt, event->system, \
+ event->name, ##__VA_ARGS__); \
+ else \
+ warning(fmt, ##__VA_ARGS__); \
+ } while (0)
+
static void init_input_buf(const char *buf, unsigned long long size)
{
input_buf = buf;
@@ -1355,7 +1367,7 @@ static int event_read_fields(struct event_format *event, struct format_field **f
}
if (!field->type) {
- do_warning("%s: no type found", __func__);
+ do_warning_event(event, "%s: no type found", __func__);
goto fail;
}
field->name = last_token;
@@ -1402,7 +1414,7 @@ static int event_read_fields(struct event_format *event, struct format_field **f
free_token(token);
type = read_token(&token);
if (type == EVENT_NONE) {
- do_warning("failed to find token");
+ do_warning_event(event, "failed to find token");
goto fail;
}
}
@@ -1636,7 +1648,7 @@ process_cond(struct event_format *event, struct print_arg *top, char **tok)
right = alloc_arg();
if (!arg || !left || !right) {
- do_warning("%s: not enough memory!", __func__);
+ do_warning_event(event, "%s: not enough memory!", __func__);
/* arg will be freed at out_free */
free_arg(left);
free_arg(right);
@@ -1686,7 +1698,7 @@ process_array(struct event_format *event, struct print_arg *top, char **tok)
arg = alloc_arg();
if (!arg) {
- do_warning("%s: not enough memory!", __func__);
+ do_warning_event(event, "%s: not enough memory!", __func__);
/* '*tok' is set to top->op.op. No need to free. */
*tok = NULL;
return EVENT_ERROR;
@@ -1792,7 +1804,7 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok)
if (arg->type == PRINT_OP && !arg->op.left) {
/* handle single op */
if (token[1]) {
- do_warning("bad op token %s", token);
+ do_warning_event(event, "bad op token %s", token);
goto out_free;
}
switch (token[0]) {
@@ -1802,7 +1814,7 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok)
case '-':
break;
default:
- do_warning("bad op token %s", token);
+ do_warning_event(event, "bad op token %s", token);
goto out_free;
}
@@ -1888,7 +1900,7 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok)
char *new_atom;
if (left->type != PRINT_ATOM) {
- do_warning("bad pointer type");
+ do_warning_event(event, "bad pointer type");
goto out_free;
}
new_atom = realloc(left->atom.atom,
@@ -1930,7 +1942,7 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok)
type = process_array(event, arg, tok);
} else {
- do_warning("unknown op '%s'", token);
+ do_warning_event(event, "unknown op '%s'", token);
event->flags |= EVENT_FL_FAILED;
/* the arg is now the left side */
goto out_free;
@@ -1951,7 +1963,7 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok)
return type;
out_warn_free:
- do_warning("%s: not enough memory!", __func__);
+ do_warning_event(event, "%s: not enough memory!", __func__);
out_free:
free_token(token);
*tok = NULL;
@@ -2385,7 +2397,7 @@ process_flags(struct event_format *event, struct print_arg *arg, char **tok)
field = alloc_arg();
if (!field) {
- do_warning("%s: not enough memory!", __func__);
+ do_warning_event(event, "%s: not enough memory!", __func__);
goto out_free;
}
@@ -2438,7 +2450,7 @@ process_symbols(struct event_format *event, struct print_arg *arg, char **tok)
field = alloc_arg();
if (!field) {
- do_warning("%s: not enough memory!", __func__);
+ do_warning_event(event, "%s: not enough memory!", __func__);
goto out_free;
}
@@ -2477,7 +2489,7 @@ process_hex(struct event_format *event, struct print_arg *arg, char **tok)
field = alloc_arg();
if (!field) {
- do_warning("%s: not enough memory!", __func__);
+ do_warning_event(event, "%s: not enough memory!", __func__);
goto out_free;
}
@@ -2492,7 +2504,7 @@ process_hex(struct event_format *event, struct print_arg *arg, char **tok)
field = alloc_arg();
if (!field) {
- do_warning("%s: not enough memory!", __func__);
+ do_warning_event(event, "%s: not enough memory!", __func__);
*tok = NULL;
return EVENT_ERROR;
}
@@ -2555,7 +2567,7 @@ process_dynamic_array(struct event_format *event, struct print_arg *arg, char **
free_token(token);
arg = alloc_arg();
if (!arg) {
- do_warning("%s: not enough memory!", __func__);
+ do_warning_event(event, "%s: not enough memory!", __func__);
*tok = NULL;
return EVENT_ERROR;
}
@@ -2614,13 +2626,14 @@ process_paren(struct event_format *event, struct print_arg *arg, char **tok)
/* prevous must be an atom */
if (arg->type != PRINT_ATOM) {
- do_warning("previous needed to be PRINT_ATOM");
+ do_warning_event(event, "previous needed to be PRINT_ATOM");
goto out_free;
}
item_arg = alloc_arg();
if (!item_arg) {
- do_warning("%s: not enough memory!", __func__);
+ do_warning_event(event, "%s: not enough memory!",
+ __func__);
goto out_free;
}
@@ -2721,21 +2734,24 @@ process_func_handler(struct event_format *event, struct pevent_function_handler
for (i = 0; i < func->nr_args; i++) {
farg = alloc_arg();
if (!farg) {
- do_warning("%s: not enough memory!", __func__);
+ do_warning_event(event, "%s: not enough memory!",
+ __func__);
return EVENT_ERROR;
}
type = process_arg(event, farg, &token);
if (i < (func->nr_args - 1)) {
if (type != EVENT_DELIM || strcmp(token, ",") != 0) {
- warning("Error: function '%s()' expects %d arguments but event %s only uses %d",
+ do_warning_event(event,
+ "Error: function '%s()' expects %d arguments but event %s only uses %d",
func->name, func->nr_args,
event->name, i + 1);
goto err;
}
} else {
if (type != EVENT_DELIM || strcmp(token, ")") != 0) {
- warning("Error: function '%s()' only expects %d arguments but event %s has more",
+ do_warning_event(event,
+ "Error: function '%s()' only expects %d arguments but event %s has more",
func->name, func->nr_args, event->name);
goto err;
}
@@ -2792,7 +2808,7 @@ process_function(struct event_format *event, struct print_arg *arg,
return process_func_handler(event, func, arg, tok);
}
- do_warning("function %s not defined", token);
+ do_warning_event(event, "function %s not defined", token);
free_token(token);
return EVENT_ERROR;
}
@@ -2878,7 +2894,7 @@ process_arg_token(struct event_format *event, struct print_arg *arg,
case EVENT_ERROR ... EVENT_NEWLINE:
default:
- do_warning("unexpected type %d", type);
+ do_warning_event(event, "unexpected type %d", type);
return EVENT_ERROR;
}
*tok = token;
@@ -2901,7 +2917,8 @@ static int event_read_print_args(struct event_format *event, struct print_arg **
arg = alloc_arg();
if (!arg) {
- do_warning("%s: not enough memory!", __func__);
+ do_warning_event(event, "%s: not enough memory!",
+ __func__);
return -1;
}
@@ -3481,11 +3498,12 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg
return val;
out_warning_op:
- do_warning("%s: unknown op '%s'", __func__, arg->op.op);
+ do_warning_event(event, "%s: unknown op '%s'", __func__, arg->op.op);
return 0;
out_warning_field:
- do_warning("%s: field %s not found", __func__, arg->field.name);
+ do_warning_event(event, "%s: field %s not found",
+ __func__, arg->field.name);
return 0;
}
@@ -3591,7 +3609,8 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
}
str = malloc(len + 1);
if (!str) {
- do_warning("%s: not enough memory!", __func__);
+ do_warning_event(event, "%s: not enough memory!",
+ __func__);
return;
}
memcpy(str, data + field->offset, len);
@@ -3697,7 +3716,8 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
return;
out_warning_field:
- do_warning("%s: field %s not found", __func__, arg->field.name);
+ do_warning_event(event, "%s: field %s not found",
+ __func__, arg->field.name);
}
static unsigned long long
@@ -3742,14 +3762,16 @@ process_defined_func(struct trace_seq *s, void *data, int size,
trace_seq_terminate(&str);
string = malloc(sizeof(*string));
if (!string) {
- do_warning("%s(%d): malloc str", __func__, __LINE__);
+ do_warning_event(event, "%s(%d): malloc str",
+ __func__, __LINE__);
goto out_free;
}
string->next = strings;
string->str = strdup(str.buffer);
if (!string->str) {
free(string);
- do_warning("%s(%d): malloc str", __func__, __LINE__);
+ do_warning_event(event, "%s(%d): malloc str",
+ __func__, __LINE__);
goto out_free;
}
args[i] = (uintptr_t)string->str;
@@ -3761,7 +3783,7 @@ process_defined_func(struct trace_seq *s, void *data, int size,
* Something went totally wrong, this is not
* an input error, something in this code broke.
*/
- do_warning("Unexpected end of arguments\n");
+ do_warning_event(event, "Unexpected end of arguments\n");
goto out_free;
}
farg = farg->next;
@@ -3811,12 +3833,12 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
if (!field) {
field = pevent_find_field(event, "buf");
if (!field) {
- do_warning("can't find buffer field for binary printk");
+ do_warning_event(event, "can't find buffer field for binary printk");
return NULL;
}
ip_field = pevent_find_field(event, "ip");
if (!ip_field) {
- do_warning("can't find ip field for binary printk");
+ do_warning_event(event, "can't find ip field for binary printk");
return NULL;
}
pevent->bprint_buf_field = field;
@@ -3830,7 +3852,8 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
*/
args = alloc_arg();
if (!args) {
- do_warning("%s(%d): not enough memory!", __func__, __LINE__);
+ do_warning_event(event, "%s(%d): not enough memory!",
+ __func__, __LINE__);
return NULL;
}
arg = args;
@@ -3896,7 +3919,7 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
bptr += vsize;
arg = alloc_arg();
if (!arg) {
- do_warning("%s(%d): not enough memory!",
+ do_warning_event(event, "%s(%d): not enough memory!",
__func__, __LINE__);
goto out_free;
}
@@ -3919,7 +3942,7 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
case 's':
arg = alloc_arg();
if (!arg) {
- do_warning("%s(%d): not enough memory!",
+ do_warning_event(event, "%s(%d): not enough memory!",
__func__, __LINE__);
goto out_free;
}
@@ -3959,7 +3982,7 @@ get_bprint_format(void *data, int size __maybe_unused,
if (!field) {
field = pevent_find_field(event, "fmt");
if (!field) {
- do_warning("can't find format field for binary printk");
+ do_warning_event(event, "can't find format field for binary printk");
return NULL;
}
pevent->bprint_fmt_field = field;
@@ -4003,8 +4026,8 @@ static void print_mac_arg(struct trace_seq *s, int mac, void *data, int size,
arg->field.field =
pevent_find_any_field(event, arg->field.name);
if (!arg->field.field) {
- do_warning("%s: field %s not found",
- __func__, arg->field.name);
+ do_warning_event(event, "%s: field %s not found",
+ __func__, arg->field.name);
return;
}
}
@@ -4176,7 +4199,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
case '*':
/* The argument is the length. */
if (!arg) {
- do_warning("no argument match");
+ do_warning_event(event, "no argument match");
event->flags |= EVENT_FL_FAILED;
goto out_failed;
}
@@ -4213,7 +4236,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
case 'X':
case 'u':
if (!arg) {
- do_warning("no argument match");
+ do_warning_event(event, "no argument match");
event->flags |= EVENT_FL_FAILED;
goto out_failed;
}
@@ -4223,7 +4246,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
/* should never happen */
if (len > 31) {
- do_warning("bad format!");
+ do_warning_event(event, "bad format!");
event->flags |= EVENT_FL_FAILED;
len = 31;
}
@@ -4290,13 +4313,13 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
trace_seq_printf(s, format, (long long)val);
break;
default:
- do_warning("bad count (%d)", ls);
+ do_warning_event(event, "bad count (%d)", ls);
event->flags |= EVENT_FL_FAILED;
}
break;
case 's':
if (!arg) {
- do_warning("no matching argument");
+ do_warning_event(event, "no matching argument");
event->flags |= EVENT_FL_FAILED;
goto out_failed;
}
@@ -4306,7 +4329,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
/* should never happen */
if (len > 31) {
- do_warning("bad format!");
+ do_warning_event(event, "bad format!");
event->flags |= EVENT_FL_FAILED;
len = 31;
}
@@ -4321,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:
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
index 791c539374c7..feab94281634 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -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
diff --git a/tools/net/bpf_dbg.c b/tools/net/bpf_dbg.c
index bb31813e43dd..9a287bec695a 100644
--- a/tools/net/bpf_dbg.c
+++ b/tools/net/bpf_dbg.c
@@ -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;
diff --git a/tools/perf/Documentation/perf-bench.txt b/tools/perf/Documentation/perf-bench.txt
index 7065cd6fbdfc..4464ad770d51 100644
--- a/tools/perf/Documentation/perf-bench.txt
+++ b/tools/perf/Documentation/perf-bench.txt
@@ -48,6 +48,12 @@ SUBSYSTEM
'mem'::
Memory access performance.
+'numa'::
+ NUMA scheduling and MM benchmarks.
+
+'futex'::
+ Futex stressing benchmarks.
+
'all'::
All benchmark subsystems.
@@ -187,6 +193,22 @@ Show only the result with page faults before memset.
--no-prefault::
Show only the result without page faults before memset.
+SUITES FOR 'numa'
+~~~~~~~~~~~~~~~~~
+*mem*::
+Suite for evaluating NUMA workloads.
+
+SUITES FOR 'futex'
+~~~~~~~~~~~~~~~~~~
+*hash*::
+Suite for evaluating hash tables.
+
+*wake*::
+Suite for evaluating wake calls.
+
+*requeue*::
+Suite for evaluating requeue calls.
+
SEE ALSO
--------
linkperf:perf[1]
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index cdd8d4946dba..976b00c6cdb1 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -87,7 +87,6 @@ Default is to monitor all CPUS.
--realtime=<priority>::
Collect data with this RT SCHED_FIFO priority.
--s <symbol>::
--sym-annotate=<symbol>::
Annotate this symbol.
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 50d875d970c4..895edd32930c 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -192,13 +192,13 @@ endif
export PERL_PATH
$(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c
- $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) -t util/parse-events.l > $(OUTPUT)util/parse-events-flex.c
+ $(QUIET_FLEX)$(FLEX) -o $@ --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) util/parse-events.l
$(OUTPUT)util/parse-events-bison.c: util/parse-events.y
$(QUIET_BISON)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $(OUTPUT)util/parse-events-bison.c -p parse_events_
$(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c
- $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/pmu-flex.h -t util/pmu.l > $(OUTPUT)util/pmu-flex.c
+ $(QUIET_FLEX)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h util/pmu.l
$(OUTPUT)util/pmu-bison.c: util/pmu.y
$(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c -p perf_pmu_
@@ -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) \
diff --git a/tools/perf/arch/x86/tests/dwarf-unwind.c b/tools/perf/arch/x86/tests/dwarf-unwind.c
index b602ad93ce63..83bc2385e6d3 100644
--- a/tools/perf/arch/x86/tests/dwarf-unwind.c
+++ b/tools/perf/arch/x86/tests/dwarf-unwind.c
@@ -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;
}
diff --git a/tools/perf/arch/x86/tests/regs_load.S b/tools/perf/arch/x86/tests/regs_load.S
index 99167bf644ea..60875d5c556c 100644
--- a/tools/perf/arch/x86/tests/regs_load.S
+++ b/tools/perf/arch/x86/tests/regs_load.S
@@ -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
diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c
index 97d86d828190..ebfa163b80b5 100644
--- a/tools/perf/bench/numa.c
+++ b/tools/perf/bench/numa.c
@@ -1593,6 +1593,10 @@ static void init_params(struct params *p, const char *name, int argc, const char
p->data_rand_walk = true;
p->nr_loops = -1;
p->init_random = true;
+ p->mb_global_str = "1";
+ p->nr_proc = 1;
+ p->nr_threads = 1;
+ p->nr_secs = 5;
p->run_all = argc == 1;
}
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 21c164b8f9db..0f1e5a2f6ad7 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -404,6 +404,7 @@ static struct kvm_event *kvm_alloc_init_event(struct event_key *key)
}
event->key = *key;
+ init_stats(&event->total.stats);
return event;
}
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index eb524f91bffe..8ce62ef7f6c3 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -374,7 +374,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
session = perf_session__new(file, false, NULL);
if (session == NULL) {
- pr_err("Not enough memory for reading perf file header\n");
+ pr_err("Perf session creation failed.\n");
return -1;
}
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 8b0e1c9234d9..65a151e36067 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -174,13 +174,20 @@ static inline int perf_evsel__nr_cpus(struct perf_evsel *evsel)
static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)
{
- memset(evsel->priv, 0, sizeof(struct perf_stat));
+ int i;
+ struct perf_stat *ps = evsel->priv;
+
+ for (i = 0; i < 3; i++)
+ init_stats(&ps->res_stats[i]);
}
static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
{
evsel->priv = zalloc(sizeof(struct perf_stat));
- return evsel->priv == NULL ? -ENOMEM : 0;
+ if (evsel == NULL)
+ return -ENOMEM;
+ perf_evsel__reset_stat_priv(evsel);
+ return 0;
}
static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index c23418225c2c..802cf544202b 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -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
@@ -65,10 +73,9 @@ ifndef NO_LIBELF
ifdef LIBDW_DIR
LIBDW_CFLAGS := -I$(LIBDW_DIR)/include
LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib
-
- FEATURE_CHECK_CFLAGS-libdw-dwarf-unwind := $(LIBDW_CFLAGS)
- FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) -ldw
endif
+ FEATURE_CHECK_CFLAGS-libdw-dwarf-unwind := $(LIBDW_CFLAGS)
+ FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) -ldw
endif
# include ARCH specific config
@@ -110,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),)
@@ -187,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
@@ -278,6 +292,8 @@ else
NO_LIBELF := 1
NO_DWARF := 1
NO_DEMANGLE := 1
+ NO_LIBUNWIND := 1
+ NO_LIBDW_DWARF_UNWIND := 1
else
msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static);
endif
@@ -503,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
@@ -514,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
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index 653a8fe2db95..bfb186900ac0 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -504,6 +504,7 @@ static int do_test_code_reading(bool try_kcore)
if (ret < 0) {
if (!excl_kernel) {
excl_kernel = true;
+ perf_evlist__set_maps(evlist, NULL, NULL);
perf_evlist__delete(evlist);
evlist = NULL;
continue;
diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index 5daeae1cb4c0..2f92d6e7ee00 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -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
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index 1fbcd8bdc11b..55de44ecebef 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -86,10 +86,17 @@ static int open_file_read(struct perf_data_file *file)
static int open_file_write(struct perf_data_file *file)
{
+ int fd;
+
if (check_backup(file))
return -1;
- return open(file->path, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR);
+ fd = open(file->path, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR);
+
+ if (fd < 0)
+ pr_err("failed to open %s : %s\n", file->path, strerror(errno));
+
+ return fd;
}
static int open_file(struct perf_data_file *file)
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index a53cd0b8c151..27c2a5efe450 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -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)
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index df0238654698..562762117639 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -985,7 +985,7 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
#if _ELFUTILS_PREREQ(0, 142)
/* Get the call frame information from this dwarf */
- pf->cfi = dwarf_getcfi(dbg->dbg);
+ pf->cfi = dwarf_getcfi_elf(dwarf_getelf(dbg->dbg));
#endif
off = 0;
@@ -1441,13 +1441,15 @@ static int line_range_walk_cb(const char *fname, int lineno,
void *data)
{
struct line_finder *lf = data;
+ int err;
if ((strtailcmp(fname, lf->fname) != 0) ||
(lf->lno_s > lineno || lf->lno_e < lineno))
return 0;
- if (line_range_add_line(fname, lineno, lf->lr) < 0)
- return -EINVAL;
+ err = line_range_add_line(fname, lineno, lf->lr);
+ if (err < 0 && err != -EEXIST)
+ return err;
return 0;
}
@@ -1473,14 +1475,15 @@ static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
static int line_range_inline_cb(Dwarf_Die *in_die, void *data)
{
- find_line_range_by_line(in_die, data);
+ int ret = find_line_range_by_line(in_die, data);
/*
* We have to check all instances of inlined function, because
* some execution paths can be optimized out depends on the
- * function argument of instances
+ * function argument of instances. However, if an error occurs,
+ * it should be handled by the caller.
*/
- return 0;
+ return ret < 0 ? ret : 0;
}
/* Search function definition from function name */
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 3b7dbf51d4a9..6864661a79dd 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -6,6 +6,7 @@
#include <inttypes.h>
#include "symbol.h"
+#include "vdso.h"
#include <symbol/kallsyms.h>
#include "debug.h"
@@ -618,6 +619,7 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
GElf_Shdr shdr;
ss->adjust_symbols = (ehdr.e_type == ET_EXEC ||
ehdr.e_type == ET_REL ||
+ is_vdso_map(dso->short_name) ||
elf_section_by_name(elf, &ehdr, &shdr,
".gnu.prelink_undo",
NULL) != NULL);
diff --git a/tools/power/acpi/Makefile b/tools/power/acpi/Makefile
index d9186a2fdf06..c2c0f20067a5 100644
--- a/tools/power/acpi/Makefile
+++ b/tools/power/acpi/Makefile
@@ -89,15 +89,6 @@ else
STRIPCMD = $(STRIP) -s --remove-section=.note --remove-section=.comment
endif
-# if DEBUG is enabled, then we do not strip or optimize
-ifeq ($(strip $(DEBUG)),true)
- CFLAGS += -O1 -g -DDEBUG
- STRIPCMD = /bin/true -Since_we_are_debugging
-else
- CFLAGS += $(OPTIMIZATION) -fomit-frame-pointer
- STRIPCMD = $(STRIP) -s --remove-section=.note --remove-section=.comment
-endif
-
# --- ACPIDUMP BEGIN ---
vpath %.c \
@@ -128,7 +119,7 @@ clean:
-rm -f $(OUTPUT)acpidump
install-tools:
- $(INSTALL) -d $(DESTDIR)${bindir}
+ $(INSTALL) -d $(DESTDIR)${sbindir}
$(INSTALL_PROGRAM) $(OUTPUT)acpidump $(DESTDIR)${sbindir}
install-man:
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 47b29834a6b6..56ff9bebb577 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -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;
}
diff --git a/virt/kvm/assigned-dev.c b/virt/kvm/assigned-dev.c
index 8db43701016f..bf06577fea51 100644
--- a/virt/kvm/assigned-dev.c
+++ b/virt/kvm/assigned-dev.c
@@ -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;
diff --git a/virt/kvm/async_pf.c b/virt/kvm/async_pf.c
index 10df100c4514..06e6401d6ef4 100644
--- a/virt/kvm/async_pf.c
+++ b/virt/kvm/async_pf.c
@@ -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;
}
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index d4b601547f1f..2458a1dc2ba9 100644
--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -97,6 +97,14 @@ static void rtc_irq_eoi_tracking_reset(struct kvm_ioapic *ioapic)
bitmap_zero(ioapic->rtc_status.dest_map, KVM_MAX_VCPUS);
}
+static void kvm_rtc_eoi_tracking_restore_all(struct kvm_ioapic *ioapic);
+
+static void rtc_status_pending_eoi_check_valid(struct kvm_ioapic *ioapic)
+{
+ if (WARN_ON(ioapic->rtc_status.pending_eoi < 0))
+ kvm_rtc_eoi_tracking_restore_all(ioapic);
+}
+
static void __rtc_irq_eoi_tracking_restore_one(struct kvm_vcpu *vcpu)
{
bool new_val, old_val;
@@ -120,9 +128,8 @@ static void __rtc_irq_eoi_tracking_restore_one(struct kvm_vcpu *vcpu)
} else {
__clear_bit(vcpu->vcpu_id, ioapic->rtc_status.dest_map);
ioapic->rtc_status.pending_eoi--;
+ rtc_status_pending_eoi_check_valid(ioapic);
}
-
- WARN_ON(ioapic->rtc_status.pending_eoi < 0);
}
void kvm_rtc_eoi_tracking_restore_one(struct kvm_vcpu *vcpu)
@@ -149,10 +156,10 @@ static void kvm_rtc_eoi_tracking_restore_all(struct kvm_ioapic *ioapic)
static void rtc_irq_eoi(struct kvm_ioapic *ioapic, struct kvm_vcpu *vcpu)
{
- if (test_and_clear_bit(vcpu->vcpu_id, ioapic->rtc_status.dest_map))
+ if (test_and_clear_bit(vcpu->vcpu_id, ioapic->rtc_status.dest_map)) {
--ioapic->rtc_status.pending_eoi;
-
- WARN_ON(ioapic->rtc_status.pending_eoi < 0);
+ rtc_status_pending_eoi_check_valid(ioapic);
+ }
}
static bool rtc_irq_check_coalesced(struct kvm_ioapic *ioapic)
@@ -353,10 +360,16 @@ static int ioapic_service(struct kvm_ioapic *ioapic, int irq, bool line_status)
ioapic->irr &= ~(1 << irq);
if (irq == RTC_GSI && line_status) {
+ /*
+ * pending_eoi cannot ever become negative (see
+ * rtc_status_pending_eoi_check_valid) and the caller
+ * ensures that it is only called if it is >= zero, namely
+ * if rtc_irq_check_coalesced returns false).
+ */
BUG_ON(ioapic->rtc_status.pending_eoi != 0);
ret = kvm_irq_delivery_to_apic(ioapic->kvm, NULL, &irqe,
ioapic->rtc_status.dest_map);
- ioapic->rtc_status.pending_eoi = ret;
+ ioapic->rtc_status.pending_eoi = (ret < 0 ? 0 : ret);
} else
ret = kvm_irq_delivery_to_apic(ioapic->kvm, NULL, &irqe, NULL);